设为首页 收藏本站
查看: 1238|回复: 0

[经验分享] 跨过几个坑,终于完成了我的第一个Xamarin Android App!

[复制链接]

尚未签到

发表于 2017-6-22 09:19:02 | 显示全部楼层 |阅读模式
  时间过得真快,距离上次发随笔又是一年多。作为上次发的我的第一个WP8.1应用总结的后继,这次同样的主要功能,改为实现安卓版APP。前几个月巨硬收购Xamarin,把Xamarin集成到VS里了,大大方便了我广大.net码农。由于年初脱了WP的坑,换了个安卓低端机,想着什么时候装Xamarin开发个App玩玩。
  上个月笔记本100G的C盘莫名其妙快满了,趁着重装系统的机会,安装了VS2015 with sp3,下载开发Android App需要的各种东东。这里要感谢【C#】VS2015开发环境的安装和配置系列文章,2016-07-03更新的,已经算是最新的vs2015 with update3的安装说明了。可惜看到这篇文章还是有点相见恨晚,文章里的流程是先下载安装JDK和Android SDK等,最后安装VS,我反过来做,浪费了一些时间。PS:对于使用Hyper-V的同学,可以使用VS自带的安卓模拟器,省却了下载和安装GOOGLE模拟器的一堆时间,据说GOOGLE模拟器还挺坑。。。
  ================================扯得太多,言归正传======================================
  App项目用的是VS里的Android Blank App,先上个图让大家看看我手机上的显示效果,自己用就不需要那么华丽丽了(关键是不会。。。)。
DSC0000.png

  Android App使用的是显示与逻辑分离的设计模式,虽然我基本是做Winform的,也是基本能看懂的。Resources\layout文件夹里放视图文件,而代码逻辑文件放在最外层,整个项目的结构如下图:
DSC0001.png

  这个App主界面使用的是GridLayout进行垂直布局,用法类似于HTML中的Table和WPF中的Grid,代码如下:


DSC0002.gif DSC0003.gif


1 <?xml version="1.0" encoding="utf-8"?>
2 <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
3     android:layout_width="match_parent"
4     android:layout_height="match_parent"
5     android:orientation="horizontal"
6     android:paddingLeft="10dp"
7     android:paddingRight="10dp"
8     android:rowCount="6"
9     android:columnCount="2">
10     <TextView
11         android:id="@+id/tvMachineCode"
12         android:layout_width="wrap_content"
13         android:layout_marginRight="5dp"
14         android:textSize="20sp"
15         android:layout_marginTop="50dp"
16         android:text="机器码" />
17     <EditText
18         android:id="@+id/txtMachineCode"
19         android:textSize="20sp"
20         android:maxLength ="20"
21         android:layout_marginTop="50dp"
22         android:layout_width="fill_parent" />
23     <TextView
24         android:id="@+id/tvActiviationCode"
25         android:layout_width="wrap_content"
26         android:layout_marginRight="5dp"
27         android:textSize="20sp"
28         android:layout_marginTop="30dp"
29         android:text="激活码" />
30     <EditText
31         android:id="@+id/txtActiviationCode"
32         android:textSize="20sp"
33         android:layout_marginTop="30dp"
34         android:layout_width="fill_parent" />
35     <Button
36         android:id="@+id/btnGetActiviationCode"
37         android:layout_marginTop="30dp"
38         android:layout_columnSpan="2"
39         android:layout_width="match_parent"
40         android:text="获取激活码" />
41     <Button
42         android:id="@+id/btnScanQRCode"
43         android:layout_columnSpan="2"
44         android:layout_width="match_parent"
45         android:text="扫描二维码" />
46     <Button
47         android:id="@+id/btnReadQRCode"
48         android:layout_columnSpan="2"
49         android:layout_width="match_parent"
50         android:text="读取二维码" />
51   <Button
52       android:id="@+id/btnCopy"
53       android:layout_columnSpan="2"
54       android:layout_width="match_parent"
55       android:text="复制激活码" />
56   <Button
57       android:id="@+id/btnShare"
58       android:layout_columnSpan="2"
59       android:layout_width="match_parent"
60       android:text="发送激活码" />
61     <Button
62         android:id="@+id/btnClear"
63         android:layout_columnSpan="2"
64         android:layout_width="match_parent"
65         android:text="清除" />
66 </GridLayout>
Main.axml  界面设计好之后,开始写逻辑代码。App默认是从MainActivity开始启动(JAVA开发可以在Properties\AndroidManifest.xml中修改,有谁知道Xamarin里是怎么改的?)。开始实现第一个按钮的功能,自我感觉还是比较容易的,基本可以直接复制粘贴我Winform里的代码,然而,我发现掉到第一个坑里去了。先看看从Winform里复制来的字符串取MD5的代码,这个在VS自带的模拟器中执行是正常的,得到的结果与Winform一致,但安装到手机里得到的就不对了。



1         private string MD5(string str, bool clearsplitter = true, bool islower = true)
2         {
3             var md5 = MD5CryptoServiceProvider.Create();
4             var output = md5.ComputeHash(Encoding.Default.GetBytes(str));
5             StringBuilder strbvalue = new StringBuilder(BitConverter.ToString(output).Replace("-", string.Empty).Substring(8, 16));
6             if (!clearsplitter)
7                 strbvalue.Insert(12, '-').Insert(8, '-').Insert(4, '-');
8             return islower ? strbvalue.ToString().ToLower() : strbvalue.ToString().ToUpper();
9         }
  上网查了下,也问了下别人,电脑里Encoding.Default用的编码是GB2312,而手机里可能是ASCII。由于不能修改之前的代码,只能改这个了,把Encoding.Default改成了Encoding.GetEncoding("gb2312"),结果出乎预料,竟然闪退了。。。又上网搜了下,需要引用Xamarin安装自带的I18N.CJK,总算是搞定了第一个按钮。以下是【获取激活码】和【清除】的代码:





        private void Btngetactiviationcode_Click(object sender, EventArgs e)
{
string strerr = ValidateFormat(txtMachineCode.Text);
if (strerr != string.Empty)
{
var dlg = new AlertDialog.Builder(this).SetTitle("警告")
.SetMessage("输入的机器码格式不正确!\n" + strerr);
dlg.Show();
Btnclear_Click(this, null);
return;
}
txtActiviationCode.Text = GetActiveCode(txtMachineCode.Text);
}
private void Btnclear_Click(object sender, EventArgs e)
{
txtMachineCode.Text = txtActiviationCode.Text = string.Empty;
}
private string GetActiveCode(string machinecode)
{
string guid = "cd89e66c-b897-4ed8-a19f-ef5a30846f0a";
return MD5(machinecode + MD5(guid, false, false), false, false);
}
private string MD5(string str, bool clearsplitter = true, bool islower = true)
{
var md5 = MD5CryptoServiceProvider.Create();
var output = md5.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(str));
StringBuilder strbvalue = new StringBuilder(BitConverter.ToString(output).Replace("-", string.Empty).Substring(8, 16));
if (!clearsplitter)
strbvalue.Insert(12, '-').Insert(8, '-').Insert(4, '-');
return islower ? strbvalue.ToString().ToLower() : strbvalue.ToString().ToUpper();
}
【获取激活码】和【清除】    这个App的主要便利用途就是能够扫描和识别二维码,上网搜了下,使用ZXing库会比较简单,它有个.net移动开发版本叫ZXing.Net.Mobile,可以使用Nuget直接下载添加引用,由于它依赖于Xamarin.Android.Support.v4,所以也要一起下载安装。直接按照ZXing.Net.Mobile官网上的扫描二维码示例代码,就做好了最简单的二维码扫描功能。注意:要在OnCreate方法里先初始化一下:



1     MobileBarcodeScanner.Initialize(Application);


1         private async void Btnscanqrcode_Click(object sender, EventArgs e)
2         {
3             var scanner = new ZXing.Mobile.MobileBarcodeScanner();
4             var result = await scanner.Scan();
5             if (result == null)
6                 return;
7             txtMachineCode.Text = result.Text.Trim();
8             Btngetactiviationcode_Click(this, null);
9         }
  完成扫描二维码的功能,顿时信心大增,以为识别图片中的二维码也很简单,结果发现又掉第二个坑里去了。原来,ZXing.Net.Mobile里没有现成简单的识别二维码的方法,只查到可以用IBarcodeReader.Decode()方法来识别,然而它第一个参数byte[] rawRGB是个什么鬼?为毛不能提供一个Bitmap让我爽一下?!去网上搜JAVA版的都是传递Bitmap对象,再去看了下ZXing.Net.Mobile的源码,竟然是有些项目类型是Bitmap对象,有些是byte[]。没时间深究,我还是自己来弄个byte[]吧。
  印象中看到过一篇教程里介绍过这个方法,说rawRGB参数指的是每个像素点的RGB值数组,而不是图像文件的二进制数组,这就要读取图像中的所有点的颜色值到数组里里再传递了。



1         private void Btnreadqrcode_Click(object sender, EventArgs e)
2         {
3             Intent = new Intent();
4             //从文件浏览器和相册等选择图像文件
5             Intent.SetType("image/*");
6             Intent.SetAction(Intent.ActionGetContent);
7             StartActivityForResult(Intent, 1);
8         }
9
10         protected override void OnActivityResult(int requestCode, [GeneratedEnum] Android.App.Result resultCode, Intent data)
11         {
12             base.OnActivityResult(requestCode, resultCode, data);
13             if(requestCode == 1 && resultCode == Android.App.Result.Ok && data != null)
14             {
15                 // create a barcode reader instance
16                 IBarcodeReader reader = new BarcodeReader();
17                 // load a bitmap
18                 int width = 0, height = 0;
19                 //像素颜色值列表(注意:一个像素的每个颜色值都是一个列表中单独的元素,
20                 //后面将会把像素颜色值转换成ARGB32格式的颜色,每个像素颜色值就有4个元素加入到列表中)
21                 List<byte> pixelbytelist = new List<byte>();
22                 try
23                 {
24                     //根据选择的文件路径生成Bitmap对象
25                     using (Bitmap bmp = Android.Provider.MediaStore.Images.Media.GetBitmap(ContentResolver, data.Data))
26                     {
27                         width = bmp.Width; //图像宽度
28                         height = bmp.Height;  //图像高度
29                         // detect and decode the barcode inside the bitmap
30                         bmp.LockPixels();
31                         int[] pixels = new int[width * height];
32                         //一次性读取所有像素的颜色值(一个整数)到pixels
33                         bmp.GetPixels(pixels, 0, width, 0, 0, width, height);
34                         bmp.UnlockPixels();
35                         for (int i = 0; i < pixels.Length; i++)
36                         {
37                             int p = pixels;  //取出一个像素颜色值
38                             //将像素颜色值中的alpha颜色(透明度)添加到列表
39                             pixelbytelist.Add((byte)Color.GetAlphaComponent(p));
40                             //将像素颜色值中的红色添加到列表
41                             pixelbytelist.Add((byte)Color.GetRedComponent(p));
42                             //将像素颜色值中的绿色添加到列表
43                             pixelbytelist.Add((byte)Color.GetGreenComponent(p));
44                             //将像素颜色值中的蓝色添加到列表
45                             pixelbytelist.Add((byte)Color.GetBlueComponent(p));
46                         }
47                     }
48                     //识别
49                     var result = reader.Decode(pixelbytelist.ToArray(), width, height, RGBLuminanceSource.BitmapFormat.ARGB32);
50                     if (result != null)
51                     {
52                         txtMachineCode.Text = result.Text.Trim();
53                         Btngetactiviationcode_Click(this, null);
54                     }
55                     else
56                         Toast.MakeText(this, "未能识别到二维码!", ToastLength.Short).Show();
57                 }
58                 catch (Exception ex)
59                 {
60                     var dlg = new AlertDialog.Builder(this).SetTitle("警告")
61                         .SetMessage("获取图像时发生错误!\n" + ex.ToString());
62                     dlg.Show();
63                 }
64             }
65         }
  上面就完成了识别二维码的功能,不过上面红色文字那里又出现个只在手机上出现的诡异问题,识别出来的二维码后面会多出一个不可见的字符,它会影响EditText中Text的长度,但不影响Text的值,可以被删除,删除前后计算出的激活码是相同的。没有去看源码,不知道怎么产生的,有人知道吗?
  后面的复制激活码和发送激活码比较简单,都是直接找的网上的代码,调用系统功能来做。





1         private void Btncopy_Click(object sender, EventArgs e)
2         {
3             ClipboardManager clip = (ClipboardManager)GetSystemService(ClipboardService);
4             StringBuilder strbcontent = new StringBuilder();
5             strbcontent.AppendLine("机器码:" + txtMachineCode.Text)
6                 .AppendLine("激活码:" + txtActiviationCode.Text);
7             ClipData clipdata = ClipData.NewPlainText("激活码", strbcontent.ToString());
8             clip.PrimaryClip = clipdata;
9             Toast.MakeText(this, "激活码已复制到剪贴板", ToastLength.Short).Show();
10         }
11
12         private void Btnshare_Click(object sender, EventArgs e)
13         {
14             if (string.IsNullOrWhiteSpace(txtActiviationCode.Text))
15             {
16                 var dlg = new AlertDialog.Builder(this).SetTitle("警告")
17                     .SetMessage("请先获取激活码!");
18                 dlg.Show();
19                 return;
20             }
21             string strerr = ValidateFormat(txtMachineCode.Text);
22             if (strerr != string.Empty)
23             {
24                 var dlg = new AlertDialog.Builder(this).SetTitle("警告")
25                     .SetMessage("输入的机器码格式不正确!\n" + strerr);
26                 dlg.Show();
27                 return;
28             }
29             Intent intent = new Intent(Intent.ActionSend);
30             intent.SetType("text/plain");//所有可以分享文本的app
31             StringBuilder strbcontent = new StringBuilder();
32             strbcontent.AppendLine("机器码:" + txtMachineCode.Text)
33                 .AppendLine("激活码:" + txtActiviationCode.Text);
34             intent.PutExtra(Intent.ExtraText, strbcontent.ToString());
35             StartActivity(Intent.CreateChooser(intent, "发送激活码"));
36         }
37
38         private string ValidateFormat(string str)
39         {
40             if(str.Length<19)
41                 return "输入的格式不正确";
42             if (str.Length != 19)
43                 str = str.Substring(0, 19);
44             string[] strs = str.Split('-');
45             if (strs.Length != 4)
46                 return "不能分隔为4组";
47             foreach (string s in strs)
48             {
49                 if (s.Length != 4)
50                     return s + "的长度不是4";
51                 if (!System.Text.RegularExpressions.Regex.IsMatch(s, "^[A-F0-9]{4}$"))
52                     return s + "的格式不正确";
53             }
54             return string.Empty;
55         }
【复制激活码】和【发送激活码】  断断续续写了几个晚上,终于写完这篇随笔了。在眼睛彻底睁不开之前赶紧贴上完整代码。





  1 using System;
  2 using Android.App;
  3 using Android.Content;
  4 using Android.Runtime;
  5 using Android.Views;
  6 using Android.Widget;
  7 using Android.OS;
  8 using System.Text;
  9 using System.Security.Cryptography;
10 using ZXing.Mobile;
11 using Android.Graphics;
12 using ZXing;
13 using Android.Database;
14 using System.Collections.Generic;
15
16 namespace FMSKeygen_Android
17 {
18     [Activity(Label = "流程管理系统注册机", MainLauncher = true, Icon = "@drawable/icon")]
19     public class MainActivity : Activity
20     {
21         private EditText txtMachineCode = null;
22         private EditText txtActiviationCode = null;
23
24         protected override void OnCreate(Bundle bundle)
25         {
26             base.OnCreate(bundle);
27
28             // Set our view from the "main" layout resource
29             SetContentView(Resource.Layout.Main);
30
31             // 初始化二维码扫描仪,后面要用到
32             MobileBarcodeScanner.Initialize(Application);
33
34             txtMachineCode = FindViewById<EditText>(Resource.Id.txtMachineCode);
35             //设置自动转换小写字母为大写
36             txtMachineCode.SetFilters(new Android.Text.IInputFilter[] { new Android.Text.InputFilterAllCaps() });
37             txtActiviationCode = FindViewById<EditText>(Resource.Id.txtActiviationCode);
38             //取消对验证码文本框的所有按键监听
39             txtActiviationCode.KeyListener = null;
40             Button btnclear = FindViewById<Button>(Resource.Id.btnClear);
41             btnclear.Click += Btnclear_Click;
42             Button btngetactiviationcode = FindViewById<Button>(Resource.Id.btnGetActiviationCode);
43             btngetactiviationcode.Click += Btngetactiviationcode_Click;
44             Button btnscanqrcode = FindViewById<Button>(Resource.Id.btnScanQRCode);
45             btnscanqrcode.Click += Btnscanqrcode_Click;
46             Button btncopy = FindViewById<Button>(Resource.Id.btnCopy);
47             btncopy.Click += Btncopy_Click;
48             Button btnreadqrcode = FindViewById<Button>(Resource.Id.btnReadQRCode);
49             btnreadqrcode.Click += Btnreadqrcode_Click;
50             Button btnshare = FindViewById<Button>(Resource.Id.btnShare);
51             btnshare.Click += Btnshare_Click;
52         }
53         
54
55         private void Btnshare_Click(object sender, EventArgs e)
56         {
57             if (string.IsNullOrWhiteSpace(txtActiviationCode.Text))
58             {
59                 var dlg = new AlertDialog.Builder(this).SetTitle("警告")
60                     .SetMessage("请先获取激活码!");
61                 dlg.Show();
62                 return;
63             }
64             string strerr = ValidateFormat(txtMachineCode.Text);
65             if (strerr != string.Empty)
66             {
67                 var dlg = new AlertDialog.Builder(this).SetTitle("警告")
68                     .SetMessage("输入的机器码格式不正确!\n" + strerr);
69                 dlg.Show();
70                 return;
71             }
72             Intent intent = new Intent(Intent.ActionSend);
73             intent.SetType("text/plain");//所有可以分享文本的app
74             StringBuilder strbcontent = new StringBuilder();
75             strbcontent.AppendLine("机器码:" + txtMachineCode.Text)
76                 .AppendLine("激活码:" + txtActiviationCode.Text);
77             intent.PutExtra(Intent.ExtraText, strbcontent.ToString());
78             StartActivity(Intent.CreateChooser(intent, "发送激活码"));
79         }
80
81         private string ValidateFormat(string str)
82         {
83             if(str.Length<19)
84                 return "输入的格式不正确";
85             if (str.Length != 19)
86                 str = str.Substring(0, 19);
87             string[] strs = str.Split('-');
88             if (strs.Length != 4)
89                 return "不能分隔为4组";
90             foreach (string s in strs)
91             {
92                 if (s.Length != 4)
93                     return s + "的长度不是4";
94                 if (!System.Text.RegularExpressions.Regex.IsMatch(s, "^[A-F0-9]{4}$"))
95                     return s + "的格式不正确";
96             }
97             return string.Empty;
98         }
99
100         private void Btnreadqrcode_Click(object sender, EventArgs e)
101         {
102             Intent = new Intent();
103             //从文件浏览器和相册等选择图像文件
104             Intent.SetType("image/*");
105             Intent.SetAction(Intent.ActionGetContent);
106             StartActivityForResult(Intent, 1);
107         }
108
109         protected override void OnActivityResult(int requestCode, [GeneratedEnum] Android.App.Result resultCode, Intent data)
110         {
111             base.OnActivityResult(requestCode, resultCode, data);
112             if(requestCode == 1 && resultCode == Android.App.Result.Ok && data != null)
113             {
114                 // create a barcode reader instance
115                 IBarcodeReader reader = new BarcodeReader();
116                 // load a bitmap
117                 int width = 0, height = 0;
118                 //像素颜色值列表(注意:一个像素的每个颜色值都是一个列表中单独的元素,
119                 //后面将会把像素颜色值转换成ARGB32格式的颜色,每个像素颜色值就有4个元素加入到列表中)
120                 List<byte> pixelbytelist = new List<byte>();
121                 try
122                 {
123                     //根据选择的文件路径生成Bitmap对象
124                     using (Bitmap bmp = Android.Provider.MediaStore.Images.Media.GetBitmap(ContentResolver, data.Data))
125                     {
126                         width = bmp.Width; //图像宽度
127                         height = bmp.Height;  //图像高度
128                         // detect and decode the barcode inside the bitmap
129                         bmp.LockPixels();
130                         int[] pixels = new int[width * height];
131                         //一次性读取所有像素的颜色值(一个整数)到pixels
132                         bmp.GetPixels(pixels, 0, width, 0, 0, width, height);
133                         bmp.UnlockPixels();
134                         for (int i = 0; i < pixels.Length; i++)
135                         {
136                             int p = pixels;  //取出一个像素颜色值
137                             //将像素颜色值中的alpha颜色(透明度)添加到列表
138                             pixelbytelist.Add((byte)Color.GetAlphaComponent(p));
139                             //将像素颜色值中的红色添加到列表
140                             pixelbytelist.Add((byte)Color.GetRedComponent(p));
141                             //将像素颜色值中的绿色添加到列表
142                             pixelbytelist.Add((byte)Color.GetGreenComponent(p));
143                             //将像素颜色值中的蓝色添加到列表
144                             pixelbytelist.Add((byte)Color.GetBlueComponent(p));
145                         }
146                     }
147                     //识别
148                     var result = reader.Decode(pixelbytelist.ToArray(), width, height, RGBLuminanceSource.BitmapFormat.ARGB32);
149                     if (result != null)
150                     {
151                         txtMachineCode.Text = result.Text.Trim();
152                         Btngetactiviationcode_Click(this, null);
153                     }
154                     else
155                         Toast.MakeText(this, "未能识别到二维码!", ToastLength.Short).Show();
156                 }
157                 catch (Exception ex)
158                 {
159                     var dlg = new AlertDialog.Builder(this).SetTitle("警告")
160                         .SetMessage("获取图像时发生错误!\n" + ex.ToString());
161                     dlg.Show();
162                 }
163             }
164         }
165
166         private void Btncopy_Click(object sender, EventArgs e)
167         {
168             ClipboardManager clip = (ClipboardManager)GetSystemService(ClipboardService);
169             StringBuilder strbcontent = new StringBuilder();
170             strbcontent.AppendLine("机器码:" + txtMachineCode.Text)
171                 .AppendLine("激活码:" + txtActiviationCode.Text);
172             ClipData clipdata = ClipData.NewPlainText("激活码", strbcontent.ToString());
173             clip.PrimaryClip = clipdata;
174             Toast.MakeText(this, "激活码已复制到剪贴板", ToastLength.Short).Show();
175         }
176
177         private async void Btnscanqrcode_Click(object sender, EventArgs e)
178         {
179             var scanner = new ZXing.Mobile.MobileBarcodeScanner();
180             var result = await scanner.Scan();
181             if (result == null)
182                 return;
183             txtMachineCode.Text = result.Text.Trim();
184             Btngetactiviationcode_Click(this, null);
185         }
186
187         private void Btngetactiviationcode_Click(object sender, EventArgs e)
188         {
189             string strerr = ValidateFormat(txtMachineCode.Text);
190             if (strerr != string.Empty)
191             {
192                 var dlg = new AlertDialog.Builder(this).SetTitle("警告")
193                     .SetMessage("输入的机器码格式不正确!\n" + strerr);
194                 dlg.Show();
195                 Btnclear_Click(this, null);
196                 return;
197             }
198             txtActiviationCode.Text = GetActiveCode(txtMachineCode.Text);
199         }
200
201         private void Btnclear_Click(object sender, EventArgs e)
202         {
203             txtMachineCode.Text = txtActiviationCode.Text = string.Empty;
204         }
205
206         private string GetActiveCode(string machinecode)
207         {
208             string guid = "cd89e66c-b897-4ed8-a19f-ef5a30846f0a";
209             return MD5(machinecode + MD5(guid, false, false), false, false);
210         }
211
212         private string MD5(string str, bool clearsplitter = true, bool islower = true)
213         {
214             var md5 = MD5CryptoServiceProvider.Create();
215             var output = md5.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(str));
216             StringBuilder strbvalue = new StringBuilder(BitConverter.ToString(output).Replace("-", string.Empty).Substring(8, 16));
217             if (!clearsplitter)
218                 strbvalue.Insert(12, '-').Insert(8, '-').Insert(4, '-');
219             return islower ? strbvalue.ToString().ToLower() : strbvalue.ToString().ToUpper();
220         }
221     }
222 }
完整代码  碎觉。。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-386722-1-1.html 上篇帖子: HTML与CSS二三事 下篇帖子: 前端 初级篇(HTML)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表