• 基于Xamarin Android实现的简单的浏览器


      最近做了一个Android浏览器,当然功能比较简单,主要实现了自己想要的一些功能……现在有好多浏览器为什么还要自己写?当你使用的时候总有那么一些地方不如意,于是就想自己写一个。

      开发环境:Xamarin Android(非Forms)+联想机子(5.0)+荣耀机子(8.0)

      【开发目标】

      1、浏览器的基本功能,关联Http和Https(在另一个APP中打开网页时,可以弹出本应用)

      2、创建应用目录,用来存放离线网页文件

      3、可以离线保存网页(格式为mht)

      4、关联mht和mhtml格式的文件

      【涉及到的技术点】

      1、重写Activity中的OnBackPressed方法,实现webview回退和再按一次退出程序的功能

      2、重写Activity中的OnConfigurationChanged方法,实现横竖屏功能

      【webview相关技术点】

      1、开启一些常用的设置:JavaScriptEnabled、DomStorageEnabled(如果DomStorageEnabled不启用,网页中的下拉刷新和加载更多将不起作用;例子:百度首页加载新闻)

      2、重写WebViewClient中的ShouldOverrideUrlLoading方法,在点击打开网页中的链接时,用自己的webview中打开连接,而不是打开其他的浏览器

      3、重写WebChromeClient中的OnReceivedTitle和OnProgressChanged方法,分别获取页面标题(作为离线文件的名称)和加载进度

      4、采用事件的方式,通知主Activity关于页面加载开始、加载结束、标题、加载进度等的一些事情,进而更新UI(这里和Java的写法有些不同)

      5、页面加载进度条

      【悬浮按钮】1、全屏(退出)按钮  2、保存网页  3、扫描二维码(版本兼容问题尚未实现)

      【网址输入框】

      1、输入正确的网址之后点击输入法中的“前往”调转

      2、隐藏输入法

      以上列到的功能基本实现,最后在荣耀V10上测试时,其他的功能还好,就是在打开离线文件时也不报错,就是打不开……郁闷啊!最后查了一下也没有找到原因。这里说一下场景,以方便大神发现问题,希望大神不吝赐教。在我的联想手机上测试时发现本地文件路径是这样的:file:///storage/emulated/0/DDZMyBrowser/SavePages/1.mht  此时可以正常浏览,而V10中得到的路径是这样的,内部存储:content://com.huawei.hidisk.fileprovider/root/storage/emulated/0/DDZMyBrowser/SavePages/1.mht   SD卡:content://com.huawei.hidisk.fileprovider/root/storage/0ABF-6213/1.mht  这两个都打不开。我查询的结果,这路径应该是利用FileProvider生成的(7.0以上),哎,并非真正的android开发,并不太懂,一脸懵逼,不知道是不是因为这个原因……开始我还寄希望于将content://转为file:///格式的,但是都失败了,最后想想网上说的webview支持content://开头的啊,自己在输入框中手动修改为:file:///storage/emulated/0/DDZMyBrowser/SavePages/1.mht  发现是可以征程浏览的……

      上一下截图:

      1、应用首页

      2、再按一次退出程序

      3、横屏

      4、竖屏

      5、网页中的下拉刷新

      6、加载更多

      7、用自己的webview中打开连接,而不是打开其他的浏览器;进度条

      8、全屏

      9、离线保存

      10、关联MHT

      11、关联HTTP和HTTPS

       12、actionGo

       13、最后再来一张V10加载异常的图片

       去去去,传上去之后发现图片太大了,全是百度的图片……这事儿弄得

      最后在贴一下代码,记录一下

      CS代码:

      1 using Android.App;
      2 using Android.Widget;
      3 using Android.OS;
      4 using Android.Webkit;
      5 using System;
      6 using Android.Support.Design.Widget;
      7 using Android.Content;
      8 using Android.Views;
      9 using Java.IO;
     10 using Android.Views.InputMethods;
     11 using Android.Content.PM;
     12 using Android.Content.Res;
     13 using Android.Provider;
     14 using Android.Database;
     15 
     16 namespace DDZ.MyBrowser
     17 {
     18     /// <summary>
     19     /// 获取网页Title
     20     /// </summary>
     21     /// <param name="title"></param>
     22     public delegate void MyWebViewTitleDelegate(string title);
     23 
     24     /// <summary>
     25     /// 获取网页加载进度
     26     /// </summary>
     27     public delegate void MyWebViewProgressChangedDelegate(int newProgress);
     28 
     29     /// <summary>
     30     /// 网页加载完成事件
     31     /// </summary>
     32     public delegate void MyWebViewPageFinishedDelegate();
     33 
     34     [IntentFilter(
     35         new[] { Intent.ActionView },
     36         Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
     37         DataSchemes = new[] { "http", "https" })]
     38     [IntentFilter(
     39         new[] { Intent.ActionView },
     40         Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
     41         DataSchemes = new[] { "file", "content" }, DataMimeType = "*/*", DataHost = "*", DataPathPattern = ".*\\.mhtml")]
     42     [IntentFilter(
     43         new[] { Intent.ActionView },
     44         Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
     45         DataMimeType = "*/*", DataSchemes = new[] { "file", "content" }, DataHost = "*", DataPathPattern = ".*\\.mht")]
     46     [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true,
     47         ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.KeyboardHidden)]
     48     public class MainActivity : Activity
     49     {
     50         WebView myBrowser;
     51         EditText edtTxtUrl;
     52         FloatingActionButton fabMain;
     53         FloatingActionButton fabSubQRcodeScan;
     54         FloatingActionButton fabSubToggleFullScreen;
     55         FloatingActionButton fabSubSaveMHT;
     56         ProgressBar myBrowserPBar;
     57 
     58         private static bool isFabOpen;
     59         private static bool isFullScreen;
     60         private static DateTime lastClickGoBack = DateTime.Now;
     61 
     62         private static string currentPageTitle;
     63         private readonly string externalStorageDirPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
     64         private readonly string selfFolderName = "DDZMyBrowser";
     65         private static string selfApplicationDirPath;
     66         protected override void OnCreate(Bundle savedInstanceState)
     67         {
     68             // https://blog.csdn.net/niunan/article/details/71774292
     69             base.OnCreate(savedInstanceState);
     70             // Set our view from the "main" layout resource
     71             SetContentView(Resource.Layout.activity_main);
     72 
     73             //  1、浏览器控件相关
     74             myBrowser = FindViewById<WebView>(Resource.Id.myBrowser);
     75             //  要与Javascript交互,则webview必须设置支持Javascript
     76             myBrowser.Settings.JavaScriptEnabled = true;
     77             //  支持通过JS打开新窗口 
     78             myBrowser.Settings.JavaScriptCanOpenWindowsAutomatically = true;
     79             myBrowser.Settings.DomStorageEnabled = true;
     80             myBrowser.Settings.AllowFileAccessFromFileURLs = true;
     81 
     82             var myWebViewClient = new MyWebViewClient();
     83             myWebViewClient.GetWebViewPageFinishedDelegate += MyWebViewClient_GetWebViewPageFinishedDelegate;
     84             myBrowser.SetWebViewClient(myWebViewClient);
     85             var myWebChromeClient = new MyWebChromeClient();
     86             myWebChromeClient.GetWebViewTitleDelegate += MyWebChromeClient_GetWebViewTitleDelegate;
     87             myWebChromeClient.GetWebViewProgressChangedDelegate += MyWebChromeClient_GetWebViewProgressChangedDelegate;
     88             myBrowser.SetWebChromeClient(myWebChromeClient);
     89             edtTxtUrl = FindViewById<EditText>(Resource.Id.edtTxtUrl);
     90             edtTxtUrl.EditorAction += EdtTxtUrl_EditorAction;
     91             myBrowserPBar = FindViewById<ProgressBar>(Resource.Id.myBrowserPBar);
     92 
     93             //  2、右下方悬浮控件
     94             fabMain = FindViewById<FloatingActionButton>(Resource.Id.fabMain);
     95             fabSubQRcodeScan = FindViewById<FloatingActionButton>(Resource.Id.fabSubQRcodeScan);
     96             fabSubToggleFullScreen = FindViewById<FloatingActionButton>(Resource.Id.fabSubToggleFullScreen);
     97             fabSubSaveMHT = FindViewById<FloatingActionButton>(Resource.Id.fabSubSaveMHT);
     98             fabMain.Click += FabMain_Click;
     99             fabSubQRcodeScan.Click += FabSubQRcodeScan_Click;
    100             fabSubToggleFullScreen.Click += FabSubToggleFullScreen_Click; ;
    101             fabSubSaveMHT.Click += FabSubSaveMHT_Click;
    102 
    103             //  3、第三方应用使用该应用打开网页时,"this.Intent.DataString" 获取需要打开的网址
    104             //      自己打开时,"this.Intent.DataString" 的值为空
    105             String url = this.Intent.DataString;
    106             if (!String.IsNullOrEmpty(url))
    107             {              
    108                 if (this.Intent.Data.Scheme == "content")
    109                 {
    110                     //  DocumentsContract.IsDocumentUri(this, this.Intent.Data):false
    111 
    112                     //  this.Intent.Data.Authority:com.huawei.hidisk.fileprovider
    113                     //  this.Intent.Data.Host:com.huawei.hidisk.fileprovider
    114                     //  this.Intent.Data.Path:/root/storage/0ABF-6213/xxx.mht
    115                     //  this.Intent.Data.PathSegments:this.Intent.Data.Path的数组形式
    116 
    117                     //  Android.Support.V4.Content.FileProvider.GetUriForFile()
    118                     //   this.Intent.SetFlags(ActivityFlags.GrantReadUriPermission).SetFlags(ActivityFlags.GrantWriteUriPermission);
    119                 }
    120             }
    121             edtTxtUrl.Text = url;
    122             LoadOnePage(url);
    123 
    124             //  4、创建应用目录
    125             CreateSelfApplicationFolder();
    126         }       
    127 
    128         private void EdtTxtUrl_EditorAction(object sender, TextView.EditorActionEventArgs e)
    129         {
    130             string inputUrl = edtTxtUrl.Text.Trim();
    131             if (e.ActionId == ImeAction.Go)
    132             {
    133                 HideSoftInputFn();
    134                 LoadOnePage(inputUrl);
    135             }
    136         }
    137 
    138         #region 获取WebView加载页面相关信息的一些自定义事件
    139         private void MyWebViewClient_GetWebViewPageFinishedDelegate()
    140         {
    141             Toast.MakeText(this, "加载完成", ToastLength.Long).Show();
    142         }
    143 
    144         private void MyWebChromeClient_GetWebViewProgressChangedDelegate(int newProgress)
    145         {
    146             myBrowserPBar.Visibility = ViewStates.Visible;
    147             myBrowserPBar.Progress = newProgress;
    148             if (newProgress == 100)
    149             {
    150                 myBrowserPBar.Visibility = ViewStates.Gone;
    151             }
    152         }
    153 
    154         private void MyWebChromeClient_GetWebViewTitleDelegate(string title)
    155         {
    156             currentPageTitle = title;
    157         }
    158         #endregion
    159 
    160         #region 悬浮按钮
    161         private void FabMain_Click(object sender, EventArgs e)
    162         {
    163             if (!isFabOpen)
    164             {
    165                 HideSoftInputFn();
    166                 ShowFabMenu();
    167             }
    168             else
    169             {
    170                 CloseFabMenu();
    171             }
    172             SetToggleFullScreenBtnImg();
    173         }
    174 
    175         private void FabSubQRcodeScan_Click(object sender, EventArgs e)
    176         {
    177             Toast.MakeText(this, "扫描二维码", ToastLength.Long).Show();
    178         }
    179 
    180         private void FabSubSaveMHT_Click(object sender, EventArgs e)
    181         {
    182             string savePageDirPath = $"{selfApplicationDirPath}{File.Separator}SavePages";
    183             File dir = new File(savePageDirPath);
    184             if (!dir.Exists())
    185             {
    186                 bool retBool = dir.Mkdir();
    187             }
    188             myBrowser.SaveWebArchive($"{savePageDirPath}{File.Separator}{currentPageTitle}.mht");
    189         }
    190 
    191         private void FabSubToggleFullScreen_Click(object sender, EventArgs e)
    192         {
    193             if (isFullScreen)
    194             {   //  目前为全屏状态,修改为非全屏
    195                 edtTxtUrl.Visibility = ViewStates.Visible;
    196                 this.Window.ClearFlags(WindowManagerFlags.Fullscreen);
    197             }
    198             else
    199             {   //  目前为非全屏状态,修改为全屏
    200                 edtTxtUrl.Visibility = ViewStates.Gone;
    201                 this.Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
    202             }
    203             isFullScreen = !isFullScreen;
    204             SetToggleFullScreenBtnImg();
    205         }
    206 
    207         private void ShowFabMenu()
    208         {
    209             isFabOpen = true;
    210             fabSubQRcodeScan.Visibility = ViewStates.Visible;
    211             fabSubToggleFullScreen.Visibility = ViewStates.Visible;
    212             fabSubSaveMHT.Visibility = ViewStates.Visible;
    213 
    214             fabMain.Animate().Rotation(135f);
    215             fabSubQRcodeScan.Animate()
    216                .TranslationY(-600f)
    217                .Rotation(0f);
    218             fabSubToggleFullScreen.Animate()
    219                .TranslationY(-410f)
    220                .Rotation(0f);
    221             fabSubSaveMHT.Animate()
    222                 .TranslationY(-220f)
    223                 .Rotation(0f);
    224         }
    225 
    226         private void CloseFabMenu()
    227         {
    228             isFabOpen = false;
    229 
    230             fabMain.Animate().Rotation(0f);
    231             fabSubQRcodeScan.Animate()
    232                 .TranslationY(0f)
    233                 .Rotation(90f);
    234             fabSubToggleFullScreen.Animate()
    235                 .TranslationY(0f)
    236                 .Rotation(90f);
    237             fabSubSaveMHT.Animate()
    238                 .TranslationY(0f)
    239                 .Rotation(90f);
    240 
    241             fabSubQRcodeScan.Visibility = ViewStates.Gone;
    242             fabSubToggleFullScreen.Visibility = ViewStates.Gone;
    243             fabSubSaveMHT.Visibility = ViewStates.Gone;
    244         }
    245 
    246         private void SetToggleFullScreenBtnImg()
    247         {
    248             if (isFullScreen)
    249             {
    250                 fabSubToggleFullScreen.SetImageResource(Resource.Drawable.fullscreenExit);
    251             }
    252             else
    253             {
    254                 fabSubToggleFullScreen.SetImageResource(Resource.Drawable.fullscreen);
    255             }
    256         }
    257         #endregion
    258 
    259         #region 重写基类 Activity 方法
    260         public override void OnConfigurationChanged(Configuration newConfig)
    261         {
    262             base.OnConfigurationChanged(newConfig);
    263             if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait)
    264             {
    265                 edtTxtUrl.Visibility = ViewStates.Visible;
    266                 fabMain.Visibility = ViewStates.Visible;
    267                 this.Window.ClearFlags(WindowManagerFlags.Fullscreen);
    268                 isFullScreen = false;
    269                 Toast.MakeText(Application.Context, "竖屏模式!", ToastLength.Long).Show();
    270             }
    271             else
    272             {
    273                 CloseFabMenu();
    274                 edtTxtUrl.Visibility = ViewStates.Gone;
    275                 fabMain.Visibility = ViewStates.Gone;
    276                 this.Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
    277                 isFullScreen = true;
    278                 Toast.MakeText(Application.Context, "横屏模式!", ToastLength.Long).Show();
    279             }
    280         }
    281         public override void OnBackPressed()
    282         {
    283             if (myBrowser.CanGoBack())
    284             {
    285                 myBrowser.GoBack();
    286             }
    287             else
    288             {
    289                 if ((DateTime.Now - lastClickGoBack).Seconds > 2)
    290                 {
    291                     Toast.MakeText(this, $"再按一次退出程序", ToastLength.Long).Show();
    292                     lastClickGoBack = DateTime.Now;
    293                 }
    294                 else
    295                 {
    296                     this.Finish();
    297                 }
    298             }
    299         }
    300         #endregion
    301 
    302         private void LoadOnePage(String url = "")
    303         {
    304             currentPageTitle = null;
    305             if (String.IsNullOrEmpty(url)) url = "https://www.baidu.com/";
    306             myBrowser.LoadUrl(url);
    307         }
    308 
    309         private void HideSoftInputFn()
    310         {
    311             //  隐藏键盘
    312             InputMethodManager imm = (InputMethodManager)this.GetSystemService(Context.InputMethodService);
    313             imm.HideSoftInputFromWindow(edtTxtUrl.WindowToken, 0);
    314         }
    315 
    316         private void CreateSelfApplicationFolder()
    317         {
    318             selfApplicationDirPath = $"{externalStorageDirPath}{File.Separator}{selfFolderName}";
    319             File dir = new File(selfApplicationDirPath);
    320             if (!dir.Exists())
    321             {
    322                 bool retBool = dir.Mkdir();
    323             }
    324         }
    325 
    326         private String GetRealPathFromURI(Context context, Android.Net.Uri uri)
    327         {
    328             String retPath = null;
    329             if (context == null || uri == null) return retPath;
    330             Boolean isKitKat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;
    331             if (isKitKat && DocumentsContract.IsDocumentUri(context, uri))
    332             {
    333                 if (uri.Authority.Equals("com.android.externalstorage.documents", StringComparison.OrdinalIgnoreCase))
    334                 {
    335                     String docId = DocumentsContract.GetDocumentId(uri);
    336                     String[] split = docId.Split(':');
    337                     if (split[0].Equals("primary", StringComparison.OrdinalIgnoreCase))
    338                     {
    339                         retPath = Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
    340                     }
    341                 }
    342             }
    343             return retPath;
    344         }
    345 
    346         private String GetFilePathFromContentUri(Context context,Android.Net.Uri url)
    347         {
    348             String filePath = null;
    349             String[] filePathColumn = { MediaStore.MediaColumns.Data };
    350             using (ICursor cursor = context.ContentResolver.Query(url, filePathColumn, null, null, null))
    351             {
    352                 if (cursor != null && cursor.MoveToFirst())
    353                 {
    354                     int columnIndex = cursor.GetColumnIndexOrThrow(filePathColumn[0]);
    355                     if (columnIndex > -1)
    356                     {
    357                         filePath = cursor.GetString(columnIndex);
    358                     }
    359                 }
    360             }
    361             return filePath;
    362         }
    363     }
    364 
    365     public class MyWebViewClient : WebViewClient
    366     {
    367         public event MyWebViewPageFinishedDelegate GetWebViewPageFinishedDelegate;
    368         public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
    369         {
    370             view.LoadUrl(request.Url.ToString());
    371             return true;
    372         }
    373 
    374         public override void OnPageFinished(WebView view, string url)
    375         {
    376             base.OnPageFinished(view, url);
    377             GetWebViewPageFinishedDelegate();
    378         }
    379     }
    380 
    381     public class MyWebChromeClient : WebChromeClient
    382     {
    383         public event MyWebViewTitleDelegate GetWebViewTitleDelegate;//声明一个事件
    384 
    385         public event MyWebViewProgressChangedDelegate GetWebViewProgressChangedDelegate;
    386         public override void OnReceivedTitle(WebView view, string title)
    387         {
    388             base.OnReceivedTitle(view, title);
    389             GetWebViewTitleDelegate(title);
    390         }
    391 
    392         public override void OnProgressChanged(WebView view, int newProgress)
    393         {
    394             base.OnProgressChanged(view, newProgress);
    395             GetWebViewProgressChangedDelegate(newProgress);
    396         }
    397     }
    398 }
    View Code

      布局代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ProgressBar
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="3dip"
                android:max="100"
                android:progress="0"
                android:visibility="gone"
                android:id="@+id/myBrowserPBar" />
            <android.webkit.WebView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:id="@+id/myBrowser" />
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <EditText
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/edtTxtUrl"
                    android:inputType="text"
                    android:singleLine="true"
                    android:imeOptions="actionGo"
                    android:hint="请输入网址" />
            </LinearLayout>
        </LinearLayout>
        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="18dp"
            android:visibility="gone"
            android:rotation="90"
            android:src="@drawable/qrcodeScan"
            app:fabSize="mini"
            android:id="@+id/fabSubQRcodeScan" />
        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="18dp"
            android:visibility="gone"
            android:rotation="90"
            android:src="@drawable/saveMht"
            app:fabSize="mini"
            android:id="@+id/fabSubSaveMHT" />
        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="18dp"
            android:visibility="gone"
            android:rotation="90"
            app:fabSize="mini"
            android:id="@+id/fabSubToggleFullScreen" />
        <android.support.design.widget.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="10dp"
            android:src="@drawable/plus"
            app:fabSize="normal"
            android:id="@+id/fabMain" />
    </RelativeLayout>
    View Code

      用到的一些权限

    <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <uses-permission android:name="android.permission.BIND_INPUT_METHOD" />
    View Code

      到此就结束了,webview在8.0下打开content://文件失败的问题,如果有大神看到,希望帮忙解答,十分感谢!以后有机会在慢慢完善他的功能。

      【2018-06-26更新】

      昨天在小米note3测试本应用,本来是想测试一下看看能不能打开离线文件的问题,但是连关联MHT都不行,打开的时候,应用列表没有该应用……郁闷了,越淌水越深啊!

      【2018-11-08更新】

      开始因为版本兼容的问题,扫描二维码未处理,一直想着过后看看官方能不能解决,但是今天看看,还是不行……但是VS给出了解决方案:

      VS会依次提示单独安装上述的几个包,开始这个项目只安装了一个包,现在的依赖如下:

      这次添加的相机权限

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

      相机相关代码

      1、初始化

            protected override void OnCreate(Bundle savedInstanceState)
            {
                ………………
                ………………
                //  5、初始化
                MobileBarcodeScanner.Initialize(Application);
            }

      2、点击扫描二维码执行的代码

            private void FabSubQRcodeScan_Click(object sender, EventArgs e)
            {
                //Toast.MakeText(this, "扫描二维码", ToastLength.Long).Show();
                Task.Run(() =>
                {
                    var scanner = new MobileBarcodeScanner();
                    var result = scanner.Scan();
                    if (result != null)
                    {
                        string scanResult = result.Result.Text;
                        this.RunOnUiThread(new Java.Lang.Runnable(() =>
                        {
                            edtTxtUrl.Text = scanResult;
                            LoadOnePage(scanResult);
                        }));
                    }
                });
            }

      经过这次更新,就可以扫描二维码了……

  • 相关阅读:
    iOS 与 惯性滚动
    前端性能优化--为什么DOM操作慢?
    React虚拟DOM浅析
    DOM性能瓶颈与Javascript性能优化
    React 组件性能优化
    重绘与回流——影响浏览器加载速度
    移动前端开发之viewport的深入理解
    [转] 前后端分离开发模式的 mock 平台预研
    [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新全然解读
    关联规则( Association Rules)之频繁模式树(FP-Tree)
  • 原文地址:https://www.cnblogs.com/du-blog/p/9221512.html
Copyright © 2020-2023  润新知