精华内容
下载资源
问答
  • 【小白成长日常】HBuilder X app如何运行到MuMu模拟器教程 可到网易官网下载MuMu模拟器 1.打开MuMu模拟器; 2.在HBuilder中运行app到模拟器,出现以下情况; 3.到HBuilder的安装目录,找到adb坐在的目录下,复制其...

    【小白成长日常】HBuilder X app如何运行到MuMu模拟器教程

    可到网易官网下载MuMu模拟器

    1.打开MuMu模拟器;

    2.在HBuilder中运行app到模拟器,出现以下情况;在这里插入图片描述
    3.到HBuilder的安装目录,找到adb坐在的目录下,复制其路径;
    在这里插入图片描述
    4.配置环境变量;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    5."Win+R"运行cmd;
    在这里插入图片描述
    6.查看adb的版本(adb version)
    在这里插入图片描述
    7.使用adb命令,查看连接的设备(adb devices)
    List of devices attached 设备列表
    在这里插入图片描述
    8.使用adb命令,让模拟器连上电脑(adb connect)
    MuMu的端口号为7555
    在这里插入图片描述
    9.查看连接的设备
    在这里插入图片描述
    这时候到HBuilder中发现可以检测模拟器了。
    在这里插入图片描述

    如果嫌上面的麻烦还可以直接在点击“工具”->"设置”->"运行配置”中,将Android的模拟器端口改为MuMu的端口号7555在这里插入图片描述
    以下是常用模拟器端口
    夜神模拟器 端口号:62001
    海马玩模拟器 端口号:26944
    网易MuMu模拟器 端口号:7555
    天天模拟器 端口号:6555
    AndroidStudio自带模拟器 端口号: 5554

    展开全文
  • Android DownloadManager下载管理,app更新

    千次阅读 2017-03-20 15:18:33
    日常APP的开发中,通常情况下无可避免的要与调用网络后台数据接口。关于Android 网络请求接口的方式可以点击此此处进行学习。当我们实现一个从网络下载文件的功能时候,一般设计思路是这样的:使用Http发起请求,...

    目录

    前言

    一、介绍

    二、使用事项

    三、Request类注意事项

    四、Query 类

    五、下载完成监听

    六、原理简析

    七、小结


    前言

    在日常APP的开发中,通常情况下无可避免的要与调用网络后台数据接口。关于Android 网络请求接口的方式可以点击此此处进行学习。当我们实现一个从网络下载文件的功能时候,一般设计思路是这样的:使用Http发起请求,在IntentService的线程进行中下载,再配合Handler更新UI显示保持和用户交互。那么看了本篇就不需要那么麻烦了,因为Google因为帮我们封装好了一个方便下载的API叫做Downloadmanager。下面会先详细介绍实际使用方式,最后将这个API的实现原理。

     


    本案例下载地址

    https://download.csdn.net/download/csdn_aiyang/10906816


    一、介绍

    DownloadManager是android2.3(API 9)以后系统提供下载的方法,是处理长期运行的HTTP下载的系统服务。客户端可以请求的URI被下载到一个特定的目标文件。客户端将会在后台与http交互进行下载,或者在下载失败,或者连接改变,重新启动系统后重新下载。还可以进入系统的下载管理界面查看进度。DownloadManger有两个内部类:Request 和Query。Request类可设置下载的一些属性;Query类可查询当前下载的进度等信息。三个公共方法:enqueue、query和remove。enqueue在队列中插入一个新的下载。当连接正常,并且DownloadManager准备执行这个请求时,开始自动下载。返回结果是系统提供的唯一下载ID,这个ID可以用于与这个下载相关的回调。query公共方法,用于查询下载信息。remove公共方法,用于删除下载,如果下载中则取消下载。同时会删除下载文件和记录。

     

    二、使用事项

    首先,填写好所需权限:

    <uses-permission android:name="android.permission.INTERNET" />;
    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;

    创建对象,设置下载地址:

    DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
    long id = downloadManager.enqueue(request);//每下载的一个文件对应一个id,通过此id可以查询数据

    取消下载:

    该方法返回成功取消的下载的个数。如果一个下载被取消了,所有相关联的、部分下载的和完全下载的文件都会被删除。

    downloadManager.remove(id);  
    int cancers = downloadManager.remove(id_1, id_2, id_3);  

    小案例实现代码:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private TextView down;
        private TextView progress;
        private TextView file_name;
        private ProgressBar pb_update;
        private DownloadManager downloadManager;
        private DownloadManager.Request request;
        public static String downloadUrl = "http://ucdl.25pp.com/fs08/2017/01/20/2/2_87a290b5f041a8b512f0bc51595f839a.apk";
        Timer timer;
        long id;
        TimerTask task;
        Handler handler =new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Bundle bundle = msg.getData();
                int pro = bundle.getInt("pro");
                String name  = bundle.getString("name");
                pb_update.setProgress(pro);
                progress.setText(String.valueOf(pro)+"%");
                file_name.setText(name);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            down = (TextView) findViewById(R.id.down);
            progress = (TextView) findViewById(R.id.progress);
            file_name = (TextView) findViewById(R.id.file_name);
            pb_update = (ProgressBar) findViewById(R.id.pb_update);
            down.setOnClickListener(this);
    
            //创建对象
            downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            request = new DownloadManager.Request(Uri.parse(downloadUrl));
            request.setTitle("大象投教");
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
            request.setAllowedOverRoaming(false);
            request.setMimeType("application/vnd.android.package-archive");
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            //创建目录
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
            //设置文件存放路径
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS  , "app-release.apk" ) ;
    
    
            //手写更新UI
            pb_update.setMax(100);
            final  DownloadManager.Query query = new DownloadManager.Query();
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    Cursor cursor = downloadManager.query(query.setFilterById(id));
                    if (cursor != null && cursor.moveToFirst()) {
                        if (cursor.getInt(
                                cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                            pb_update.setProgress(100);
                            install(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/app-release.apk" );
                            task.cancel();
                        }
                        String title = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                        String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                        int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                        int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                        int pro =  (bytes_downloaded * 100) / bytes_total;
                        Message msg =Message.obtain();
                        Bundle bundle = new Bundle();
                        bundle.putInt("pro",pro);
                        bundle.putString("name",title);
                        msg.setData(bundle);
                        handler.sendMessage(msg);
                    }
                    cursor.close();
                }
            };
            timer.schedule(task, 0,1000);
    
    //        downloadManager.remove(id);
        }
    
        @Override
        public void onClick(View v) {
            id = downloadManager.enqueue(request);
            task.run();
            down.setClickable(false);
        }
        private void install(String path) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//4.0以上系统弹出安装成功打开界面
            startActivity(intent);
        }
    }

    布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/file_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:text="dxtj.apk"/>
        <ProgressBar
            android:id="@+id/pb_update"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="10dp"
            android:max="100"
            android:progress="0"
            android:progressDrawable="@drawable/progressbar_color"
            android:layout_marginBottom="20dp"
            />
    
        <TextView
            android:id="@+id/progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_marginBottom="20dp"
            android:text="0%"/>
        <TextView
            android:id="@+id/down"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:paddingTop="10dp"
            android:paddingBottom="10dp"
            android:paddingLeft="30dp"
            android:paddingRight="30dp"
            android:background="@color/colorAccent"
            android:text="立即下载"/>
    </LinearLayout>
    

    Progress_bar.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <item android:id="@android:id/background">
    
            <shape>
    
                <corners android:radius="10dip" />
    
                <gradient
                    android:angle="0"
                    android:centerColor="#e4e4e4"
                    android:centerY="0.75"
                    android:endColor="#e4e4e4"
                    android:startColor="#e4e4e4" />
            </shape>
        </item>
    
        <item android:id="@android:id/secondaryProgress">
    
            <clip>
    
                <shape>
    
                    <corners android:radius="10dip" />
    
                    <gradient
                        android:angle="0"
                        android:centerColor="#e4e4e4"
                        android:centerY="0.75"
                        android:endColor="#e4e4e4"
                        android:startColor="#e4e4e4" />
                </shape>
            </clip>
        </item>
    
        <item android:id="@android:id/progress">
    
            <clip>
    
                <shape>
    
                    <corners android:radius="10dip" />
    
                    <gradient
                        android:angle="0"
                        android:endColor="@color/colorAccent"
                        android:startColor="@color/colorAccent" />
                </shape>
            </clip>
        </item>
    
    </layer-list>
    

     

    三、Request类注意事项

     public static class Request {
            public static final int NETWORK_MOBILE = 1;
            public static final int NETWORK_WIFI = 2;
            public static final int VISIBILITY_HIDDEN = 2;
            public static final int VISIBILITY_VISIBLE = 0;
            public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
            public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3;
    }

    1、指定下载位置及文件名称:

            /**
             * 方法1: 
             * 目录: Android -> data -> com.app -> files -> Download -> dxtj.apk
             * 这个文件是你的应用所专用的,软件卸载后,下载的文件将随着卸载全部被删除
             */
            request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS ,  "dxtj.apk" );  
    
            /**
             * 方法2:
             * 下载的文件存放地址  SD卡 download文件夹,dxtj.apk
             * 软件卸载后,下载的文件会保留
             */
            //在SD卡上创建一个文件夹
            request.setDestinationInExternalPublicDir(  "/epmyg/"  , "dxtj.apk" ) ;  
    
    
            /**
             * 方法3:
             * 如果下载的文件希望被其他的应用共享
             * 特别是那些你下载下来希望被Media Scanner扫描到的文件(比如音乐文件)
             */
            request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC,  "告白气球.mp3" );  
    
            /**
             * 方法4
             * 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
             * 系统有个下载文件夹,比如小米手机系统下载文件夹  SD卡--> Download文件夹
             */
            //创建目录
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ; 
    
            //设置文件存放路径
            request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "dxtj.apk" ) ;
        

    2、指定下载的网络类型:

    //指定在WIFI状态下,执行下载操作。
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
    //指定在MOBILE状态下,执行下载操作
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
    //是否允许漫游状态下,执行下载操作
    request.setAllowedOverRoaming(boolean);
    //是否允许“计量式的网络连接”执行下载操作
    request.setAllowedOverMetered(boolean); //默认是允许的。

    3、定制Notification通知样式:

    //设置Notification的标题和描述
    request.setTitle("标题");  
    request.setDescription("描述"); 
    //设置Notification的显示,和隐藏。
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

     VISIBILITY_VISIBLE:通知显示,只是在下载任务执行的过程中显示,下载完成自动消失。(默认值) 
     VISIBILTY_HIDDEN: 通知将不会显示,如果设置该属性的话,必须要添加权限 

    Android.permission.DOWNLOAD_WITHOUT_NOTIFICATION. 

     VISIBILITY_VISIBLE_NOTIFY_COMPLETED : 通知显示,下载进行时,和完成之后都会显示。 
     VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION :下载完成时显示通知。 

     

    4、设置下载文件类型:

    request.setMimeType("application/vnd.android.package-archive");

    这是安卓.apk文件的类型。有些机型必须设置此方法,才能在下载完成后,点击通知栏的Notification时,才能正确的打开安装界面。不然会弹出一个Toast(can not open file)。其他文件类型的MimeType ,根据需求上网查一下吧 。如果设置了mimeType为application/cn.trinea.download.file,我们可以同时设置某个Activity的intent-filter为application/cn.trinea.download.file,用于响应点击的打开文件。

       <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
    
                    <data android:mimeType="application/cn.trinea.download.file" />
                </intent-filter>
            </activity>

    5、添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等:

    request.addRequestHeader(String header, String value);

    四、Query 类

    Request类中封装了Notification ,简单设置属性就显示进度信息了。有时候需要在App中获取实时下载进度。而Query类就是提供查询的一些方法。 由于downloadManager将数据保存在数据库的,所以需要获得一个Cursor 结果集,通过结果集获得我们想要的数据。

    DownloadManager.Query query = new DownloadManager.Query();
        Cursor cursor = downloadManager.query(query.setFilterById(id));
             if (cursor != null && cursor.moveToFirst()) {
            //下载的文件到本地的目录
            String address = 
                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
            //已经下载的字节数
            int bytes_downloaded =
                    cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
            //总需下载的字节数
            int bytes_total = 
                    cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
            //Notification 标题
            String title =
                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
            //描述
            String description =
                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
            //下载对应id
            long id =
                    cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
            //下载文件名称
            String filename =
                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
            //下载文件的URL链接
            String url =
                    cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
        }

    这只能获取一次,数据库中的信息。我们可以使用Timer类,每隔一段时间去查询数据库即可。也可以使用ContentProvider去访问:

        
    
        private static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
        private DownloadContentObserver observer = new DownloadContentObserver();
    
        @Override
        protected void onResume() {
            super.onResume();
            getContentResolver().registerContentObserver(CONTENT_URI, true, observer);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            getContentResolver().unregisterContentObserver(observer);
        }
    
    //ContentObserver 内部类监听下载进度
        class DownloadContentObserver extends ContentObserver {
            public DownloadContentObserver() {
                super(handler);
            }
    
            @Override
            public void onChange(boolean selfChange) {
                updateView();//更新UI
            }
    
        }

    五、下载完成监听

    下载完成后,下载管理服务会发出DownloadManager.ACTION_DOWNLOAD_COMPLETE这个广播,并传递downloadId作为参数。通过接受广播我们可以打开对下载完成的内容进行操作。

    private CompleteReceiver completeReceiver;
    
    class CompleteReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // get complete download id
            long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            // to do here
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...
        
        completeReceiver = new CompleteReceiver();
        //register download success broadcast
        registerReceiver(completeReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(completeReceiver);
    }
    
    

    六、原理简析

    DownloadManager开始下载的入口enqueue方法,这个方法的源码如下:

    public long enqueue(Request request) {
        ContentValues values = request.toContentValues(mPackageName);
        Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);
        long id = Long.parseLong(downloadUri.getLastPathSegment());
        return id;
    }
    
    

    使用的ContentProvider方式,“request.toContentValues()”,将Request信息转换为ContentValues类。

    然后调用ContentResolver进行插入“mResolver.insert()”,调用对应的ContentProvider的insert方法。传入的参数,URI是Downloads.Impl.CONTENT_URI,即"content://downloads/my_downloads",找到对应系统提供的DownloadProvider

    DownloadProvider类在系统源码的src/com/android/providers/downloads的路径下,找都其insert方法的实现,可以发现最后部分的代码:

    public Uri insert(final Uri uri, final ContentValues values) {
        ...
        // Always start service to handle notifications and/or scanning
        final Context context = getContext();
        context.startService(new Intent(context, DownloadService.class));
    
        return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, rowID);
    }
    
    

    即插入信息后,会启动DownloadService开始进行下载。(源码学习|Android N DownloadManager源码分析

    DownloadService的入口是onStartCommand方法,其中用mUpdateHandler发送消息MSG_UPDATE,mUpdateHandler处理消息的方式如下:

    mUpdateHandler = new Handler(mUpdateThread.getLooper(), mUpdateCallback);
    
    private Handler.Callback mUpdateCallback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            ...
            final boolean isActive;
            synchronized (mDownloads) {
                isActive = updateLocked();
            }
            ...
        }
    };
    
    private boolean updateLocked() {
        ...
         // Kick off download task if ready
         final boolean activeDownload = info.startDownloadIfReady(mExecutor);
        ...
    }
    
    public boolean startDownloadIfReady(ExecutorService executor) {
        synchronized (this) {
            final boolean isReady = isReadyToDownload();
            final boolean isActive = mSubmittedTask != null && !mSubmittedTask.isDone();
            if (isReady && !isActive) {
                if (mStatus != Impl.STATUS_RUNNING) {
                    mStatus = Impl.STATUS_RUNNING;
                    ContentValues values = new ContentValues();
                    values.put(Impl.COLUMN_STATUS, mStatus);
                    mContext.getContentResolver().update(getAllDownloadsUri(), values, null, null);
                }
                //启动DownloadThread开始下载任务
                mTask = new DownloadThread(mContext, mSystemFacade, mNotifier, this);
                mSubmittedTask = executor.submit(mTask);
            }
            return isReady;
        }
    }

    从上面源码可以看,DownloadService的onStartCommand方法,最终启动DownloadThread,开始下载的任务(网络请求接口使用的是HttpURLConnection)。DownloadThread在下载过程中,会更新DownloadProvider。

    综上所述,DownloadManager的enqueue方法的流程是:

    DownloadProvider插入信息 >> 启动DownloadService >> 开始DownloadThread进行下载

     

     

    七、小结

    1、我发现,在下载的时候,发送Notification时 是没有声音的。也没有设置声音的方法。不过这影响不大。主要的功能实现就好。 
    2、因为这是系统的类,每个系统的Notification界面是不一样的。这就是每个rom厂家的自定义了。小米和魅族的就大不一样。魅族Notification上有一个下载暂停的按钮,而小米没有。所以导致Notification是不能统一的。其实,暂停的话用户可以点击notification,进入到下载管理界面,就有暂停按钮了。

    3、会出现被用户手动禁用了下载器出现崩溃情况。需要做好版本兼容和弹框让用户手动开启。


    参考链接:https://www.jianshu.com/p/e0496200769c DownloadManager的使用和解析-简书

    展开全文
  • mui 日常踩坑之android退出app

    千次阅读 2017-12-09 16:29:19
    mui日常系列

    这是双击退出

    mui.oldback = mui.back;
    var clickNum = 0;
    mui.back = function(event) {
        clickNum++;
        if(clickNum > 1) {
            plus.runtime.quit();
        } else {
            mui.toast("再按一次退出应用");
        }
        setTimeout(function() {
            clickNum = 0
        }, 1000);
        return false;
    }

    这是单击退出

    mui.back = function() {
        var btn = ["确定", "取消"];
        mui.confirm('是否退出app?', '温馨提示', btn, function(e) {
            if(e.index == 0) {
                mui.currentWebview.close();
            }
        });
    }
    展开全文
  • iOS系统是相对封闭的系统,App各自在各自的沙盒(sandbox)中运行,每个App都只能读取iPhone上iOS系统为该应用程序程序创建的文件夹AppData下的内容,不能随意跨越自己的沙盒去访问别的App沙盒中的内容。1、URL ...

    本文为转载学习,原文地址

    这里写图片描述
    iOS系统是相对封闭的系统,App各自在各自的沙盒(sandbox)中运行,每个App都只能读取iPhone上iOS系统为该应用程序程序创建的文件夹AppData下的内容,不能随意跨越自己的沙盒去访问别的App沙盒中的内容。

    这里写图片描述

    1、URL Scheme

    这个是iOS app通信最常用到的通信方式,App1通过openURL的方法跳转到App2,并且在URL中带上想要的参数,有点类似http的get请求那样进行参数传递。这种方式是使用最多的最常见的,使用方法也很简单只需要源App1在info.plist中配置LSApplicationQueriesSchemes,指定目标App2的scheme;然后在目标App2的info.plist中配置好URL types,表示该app接受何种URL scheme的唤起。

    这里写图片描述

    典型的使用场景就是各开放平台SDK的分享功能,如分享到微信朋友圈微博等,或者是支付场景。比如从滴滴打车结束行程跳转到微信进行支付。

    这里写图片描述

    2、Keychain

    iOS系统的Keychain是一个安全的存储容器,它本质上就是一个sqllite数据库,它的位置存储在/private/var/Keychains/keychain-2.db,不过它所保存的所有数据都是经过加密的,可以用来为不同的app保存敏感信息,比如用户名,密码等。iOS系统自己也用keychain来保存VPN凭证和Wi-Fi密码。它是独立于每个App的沙盒之外的,所以即使App被删除之后,Keychain里面的信息依然存在。
    基于安全和独立于app沙盒的两个特性,Keychain主要用于给app保存登录和身份凭证等敏感信息,这样只要用户登录过,即使用户删除了app重新安装也不需要重新登录。
    那Keychain用于App间通信的一个典型场景也和app的登录相关,就是统一账户登录平台。使用同一个账号平台的多个app,只要其中一个app用户进行了登录,其他app就可以实现自动登录不需要用户多次输入账号和密码。一般开放平台都会提供登录SDK,在这个SDK内部就可以把登录相关的信息都写到keychain中,这样如果多个app都集成了这个SDK,那么就可以实现统一账户登录了。
    Keychain的使用比较简单,使用iOS系统提供的类KeychainItemWrapper,并通过keychain access groups就可以在应用之间共享keychain中的数据的数据了。

    这里写图片描述

    3、UIPasteboard

    顾名思义, UIPasteboard是剪切板功能,因为iOS的原生控件UITextView,UITextField 、UIWebView,我们在使用时如果长按,就会出现复制、剪切、选中、全选、粘贴等功能,这个就是利用了系统剪切板功能来实现的。而每一个App都可以去访问系统剪切板,所以就能够通过系统剪贴板进行App间的数据传输了。
    UIPasteboard的使用很简单,

    这里写图片描述

    UIPasteboard典型的使用场景就是淘宝跟微信/QQ的链接分享。由于腾讯和阿里的公司战略,腾讯在微信和qq中都屏蔽了淘宝的链接。那如果淘宝用户想通过QQ或者微信跟好友分享某个淘宝商品,怎么办呢? 阿里的工程师就巧妙的利用剪贴板实现了这个功能。首先淘宝app中将链接自定义成淘口令,引导用户进行复制,并去QQ好友对话中粘贴。然后QQ好友收到消息后再打开自己的淘宝app,淘宝app每次从后台切到前台时,就会检查系统剪切板中是否有淘口令,如果有淘口令就进行解析并跳转到对于的商品页面。
    先复制淘口令到剪切板,

    这里写图片描述

    把剪切板中的内容粘贴到微信发给微信好友,

    这里写图片描述

    微信好友把淘口令复制到淘宝中,就可以打开好友分享的淘宝链接了。

    这里写图片描述

    4、UIDocumentInteractionController

    UIDocumentInteractionController主要是用来实现同设备上app之间的共享文档,以及文档预览、打印、发邮件和复制等功能。它的使用非常简单.
    首先通过调用它唯一的类方法 interactionControllerWithURL:,并传入一个URL(NSURL),为你想要共享的文件来初始化一个实例对象。然后UIDocumentInteractionControllerDelegate,然后显示菜单和预览窗口。

    这里写图片描述

    效果如下:

    这里写图片描述

    5、local socket

    这种方式不太常见,也是很容易被iOS开发者所忽略但是特别实用的一种方法。它的原理很简单,一个App1在本地的端口port1234进行TCP的bind和listen,另外一个App2在同一个端口port1234发起TCP的connect连接,这样就可以建立正常的TCP连接,进行TCP通信了,那么就想传什么数据就可以传什么数据了。
    这种方式最大的特点就是灵活,只要连接保持着,随时都可以传任何相传的数据,而且带宽足够大。它的缺点就是因为iOS系统在任意时刻只有一个app在前台运行,那么就要通信的另外一方具备在后台运行的权限,像导航或者音乐类app。
    它是常用使用场景就是某个App1具有特殊的能力,比如能够跟硬件进行通信,在硬件上处理相关数据。而App2则没有这个能力,但是它能给App1提供相关的数据,这样APP2跟App1建立本地socket连接,传输数据到App1,然后App1在把数据传给硬件进行处理。

    这里写图片描述

    本文为转载学习使用,想看原文前往原文地址

    展开全文
  • 尾巴翻译APP产品分析

    千次阅读 2015-09-23 19:53:50
    今天介绍的尾巴app是一款旨在解决用户在出境旅游中遇到的语言问题的一款集机器内翻译和人工翻译一身的旅行翻译软件,实时高效的翻译效果得到了用户的好评。针对这款app,在下准备从六个方面进行分析,包括行业背景...
  • 今日秋高气爽,闲来无事,特此总结了一下以前做的userLogin功能,希望能给大家带来分享,如有不同的idea,欢迎下方留盐~~~ 接下来以163邮箱为例,对各位用户大大的Login做一个简单的思路介绍: ...
  • Setapp

    2019-04-05 14:54:57
    2.通过App开发提供的下载途径下载对应的应用,如CleanMyMac、百度网盘等(一次性付费方式)。Setapp的开发商MacPow(CleanMyMac X同样由该开发商开发)提出了一种新的思路,你可以把它等同于一个都是已经付费过的App ...
  • runApp(appDir = getwd(), port = getOption("shiny.port"), launch.browser = getOption("shiny.launch.browser", interactive()), host = getOption("shiny.host", "...
  • 智能体重秤方案/案列/APP/程序

    千次阅读 2019-07-09 15:38:51
    现代人的生活节奏快、饮食不规律的特点...我爱物联网研发的这款智能体重秤能够测量肌肉含量、水分含量、卡路里、体重、BMI、骨密度、脂肪含量和内脏脂肪含量八大指标,真正做到一台秤监控日常身体变化。并且配合APP...
  • 教你解决Mac App Store无法下载软件问题
  • 毕业设计So Easy:珠穆朗玛FM音频电台APP

    万次阅读 多人点赞 2021-06-01 12:50:27
    珠穆朗玛FM是一款仿照喜马拉雅(音频分享平台)APP所开发的音频分享电台APP,该应用充分实现喜马拉雅APP的诸多重要功能,如在线专辑展示、电台展示及播放、音频下载、音频录制、音频分享等功能,通过对以上多种功能...
  • 随着移动端的发展,手机已经是我们日常生活中离不开的东西了,进而也催生了一系列手机APP,特别是近年来的短视频app尤其火爆,大家都爱拍自己的视频然后剪辑上传到抖音、快手、皮皮虾等短视频平台。 爱剪辑app...
  • Android AppWidget(桌面部件)

    万次阅读 2018-08-27 15:02:35
    AppWidget是应用程序窗口部件(Widget)是微型的应用程序视图 官方文档链接:http://www.android-doc.com/guide/topics/appwidgets/index.html 目录结构(不是桌面部件开发步骤) 通过Android Studio 创建...
  • 【我想说的话:开发这个东西的初衷是为了想将所学融入日常生活中,恰好学长开发了一个i重科,我想挑战一下结合人工智能的签到app会是什么样的体验。在这个过程中我面临了很多困难,一度怀疑自己,但是现在我还是继续...
  • app测试总结

    千次阅读 多人点赞 2018-08-24 16:47:18
    此篇,记录日常工作中对app测试的常用思考点;   app测试需考虑点:  1、根据需求功能测试:等价,边界,场景;  2、工具类测试:GT、appium、monkey、monkeyrunner、adb命令;  1)、...
  • 正常情况下,在AppDelegate中实现下面两个方法,能够监听从后台恢复到前台 - (void)applicationDidEnterBackground:(UIApplication *)application  {   log4info(@"---applicationDidEnterBackground----");...
  • 如上图所示,switch的开关是使用checked属性绑定的,并无双向绑定,下面来看代码。 <view class="value"> <switch :checked="goodsItem.integralSelf" @change="integralSelfHandle" />...
  • 1.2.4产品定位 睡眠APP和蜗牛睡眠APP两个产品目前主打功能为白噪音和睡眠质量监控功能,相比较而言,蜗牛睡眠社区性更为偏重,而睡眠APP则发力在明星IP、歌曲、有声付费内容领域,可以说各有侧重。 第二部分 ...
  • 论工具类App的盈利之道

    千次阅读 2013-03-30 22:28:19
    从Android平台兴起算起,偶在移动互联网这个行业中一直摸爬滚打到现在,一直都是以一个App开发者的身份去接触这个行业,刚开始以学生身份做一些应用自娱自乐,后来也加入过创业团队弄过潮,从刚开始做一些简易的...
  • 据交管局数据信息显示:截至2016年底,新能源汽车保有量达66.32辆,其中纯电动汽车保有量40.2万辆,占...这一数据信息也从另一个侧面证实了,共享充电桩APP开发将拥有着广阔的市场。 共享充电桩APP开发拥有市场潜力...
  • 随着iOS8的发布,iTunes Connect的界面也是发生了很大的改变,App 上传到 Store上面的步骤也是发生了些改变.下面继续用图说话:/*********************************************1*************************************...
  • 随着人工智能、物联网、大数据技术的成熟与发展,智慧社区建设也如火如荼,当下智慧社区APP、智慧社区程序被年轻人的追崇,趣开门人脸识别智能门禁D508、趣开门APP、微信开门程序的投入应用,改变以往的出入模式...
  • 恰好搜到一个大神自己写的csdn的app下载安装了一下,感觉很不错,也很流畅,基本满足了我们 日常浏览的需求。 app效果图: 我会在博客中完整的介绍这个项目的制作,第一篇当然是整个项目的整体结构了。 效果...
  • uniapp最大的优势就是整合7端开发规范在一起,配合Vue让前端开发人员可以开发出“具有基本功能”的APP(对比flutter来说,uniapp对前端更友好),可以快速开发多端应用。一次编译,多端运行。 接口丰富。DCloud有h5 ...
  • 大前端开发:前端如何开发 APP

    万次阅读 多人点赞 2018-07-03 02:45:52
    做为一个前端开发人员,有时候除去传统的前端开发还需要进行其他开发,比如公众号开发,程序开发,APP 开发。 本场 Chat 将带你从0开始,基于 APICloud 进行 APP 开发,你只需要会前端就可以。 本场 Chat 主要内容...
  • App clip 是 App 应用程序的轻量级版本,可在用户需要的位置和时间提供某些功能。在 Xcode 中, App clip 是和你主应用程序共享代码和资源的附加 Target。App clip 还可以访问和 App 相同的 frameworks。例如,您的 ...
  • 社区管理系统案列/APP/程序/网站

    千次阅读 2019-07-05 17:33:54
    这种类型的O2O,运营模式偏线上,线下仅依靠地推做支撑,如若地推团队撤走,则很容易出现后续推广和服务跟不上的问题,造成客户粘度,降低了平台的可持续性发展度,最终形成恶性循环,影响线上业务的发展。...
  • APP 日常运营中,基于营销以及推广的目的,我们需要对 APP 用户推送一些活动信息或重要资讯。常见的消息推送工具分为两种:1、即技术团队自行开发; 2、第三方 Push 工具 对于许多创业型公司而言,相对于自行开发...
  • Qt模仿安卓手机中app图标移动

    千次阅读 2019-01-21 22:44:05
    一、简述 最近使用Qt中的拖拽事件加上一些动画效果模仿了安卓手机中日常用的app图标拖动,目前支持横向移动。 通过判断当前拖动鼠标的位置来进行选择是否进行动画移动前后的按钮。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 70,125
精华内容 28,050
关键字:

下载小日常app