最近因為要在back (< ) button事件中加上動畫(沒辦法,資料總是要從網路下載)
真的是試破頭殼了
其原因是因為我忘了是套用了shell架構,所以content page上方的back button點擊時是不會觸發OnBackButtonPressed 事件的 (但如果是用螢幕下方的 "<" button,是會觸發這個事件的)
好在先進有類似的情境(如,回上一頁時要先做確認的動作)
這時就可以參考這篇文章了
在此介紹給xamarin form的同好
一起加油吧!!
最近因為要在back (< ) button事件中加上動畫(沒辦法,資料總是要從網路下載)
真的是試破頭殼了
其原因是因為我忘了是套用了shell架構,所以content page上方的back button點擊時是不會觸發OnBackButtonPressed 事件的 (但如果是用螢幕下方的 "<" button,是會觸發這個事件的)
好在先進有類似的情境(如,回上一頁時要先做確認的動作)
這時就可以參考這篇文章了
在此介紹給xamarin form的同好
一起加油吧!!
osm的技術官網:
https://wiki.openstreetmap.org/wiki/API
在的網頁內嵌入osm,ref https://noob.tw/openstreetmap/
tile的觀念: http://blog.changyy.org/2012/05/openstreetmap-api.html
(觀念很重要,因為日後從緯經度推算tile一定會用到)
就static map而言,就應該是緯經度推算成tile,所以請參考以下網址
https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
有了tile,那推算出大致位置的方式,就用比例去推算了
參考這則討論
如果,你真的只是要產出幾張圖,那就到
https://www.openstreetmap.org 用右手側工具區有個「分享」iconstep 1..to resize vdi of VBox ,please refer to :
https://www.howtogeek.com/124622/how-to-enlarge-a-virtual-machines-disk-in-virtualbox-or-vmware/
File > Virtual Media Manager in the main VirtualBox window
step2 .extend to 100 free space.
ref:
https://kb.vander.host/operating-systems/how-to-resize-an-ubuntu-18-04-lvm-disk/
用sudo -i (root身份去執行)
其中,
-------------------------------------
user@server:~# parted
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) resizepart
Partition number? 3
End? [26.8GB]? <--這地方要自己輸入,不能只按enter,
因為parted 是不知道你有多少空間可以用
(在上一個指令「fdisk -l」裡「Disk /dev/sda: 30.25 GiB」就是我們可用(用步驟1改的vdi大小)的大小,
所以請在此填入32.25G)
(parted) quit Information: You may need to update /etc/fstab.
----------------------------------------------
接著用
pvresize /dev/sda3
上述才會生效
又,我是直接用「lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv」
確定它出現以下訊息
------------------------------------------
Size of logical volume ubuntu-vg/ubuntu-lv changed from <9.00 GiB (2303 extents) to 29.24 GiB (7486 extents). Logical volume ubuntu-vg/ubuntu-lv successfully resized.
---------------------------------------------
才是正確地完成了lvextend指令,
當然別忘了之後的「resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv」指令,再用df -h 確定LVM有擴充
才是真的功德圓滿了
以上,加油了!!
------------------------------------
在轉成json時常常有動態屬性的必要,這時dictionary是很需要的
以下是個不錯的extension,來源在此
直接copy paste 了
-----------------------------------------------
public static class Extensions
{
public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
public static dynamic ToDynamicObject(this IDictionary<string, object> source)
{
ICollection<KeyValuePair<string, object>> someObject = new ExpandoObject();
someObject.AddRange(source);
return someObject;
}
}
----------------------------------------------
很好用,推薦給c# codder們
---這裡沒有什麼原理解說(因為我也不懂),如果先進要補充指正的....麻煩鞭小力一點-----
先安裝.net sdk & runtime環境
ref : https://tecadmin.net/how-to-install-net-core-on-ubuntu-20-04/
裝.net之後,移駕到我們複製上去的webapi專案publish資料夾裡
用「dotnet xxxx.dll」啟動那個webapi (以vs2019提供的weatherforecase範例為例)
然後用curl http://locahost:5000/weatherforecast 測看看.net core runtime & web api有沒有起來
有出現該有的json資料,有再進行Nginx安裝
接著安裝nginx
install nginx,別忘了先去找到80 port的服務先關掉.(指令 sudo netstat -peanut|grep ":80 " )
之後.安裝nginx
----------------------
sudo apt install nginx
---------------------------
---start nginx by command---
sudo systemctl start nginx
----------------------------------
//用localhost檢查Nginx有沒有起來
因為我們新的環境允許對個別site做port&SSL 設定,
所以我們只要在nginx加個site config檔就可以
但是cert & pem是一定要做,參考黑暗大大的好文
https://blog.darkthread.net/blog/aspnetcore-with-nginx/
----------因為private目錄已經有了,所以要另外定義一個資料夾-----------------------
sudo mkdir /etc/ssl/private4ngix
sudo chmod 700 /etc/ssl/private4ngix
//以下的360是天數
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private4ngix/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
------------------------------------------
---要把port 80錯開(不然其他用到80port的東西會起不來),
最近想說MAUI快拍板定案了,那麼Xamarn.Form 這幾年經過各位大神補完下來也應該夠成熟好用了.
真正是「明仔在的窟仔,咱微軟給你挖便便啊」..呃.不是啦,是「明仔在的氣力,咱Xamarin給你傳便便啊」(碼你個B~),所以下個案子,可以考慮用xamarin.form加速開發
我個人最常在畫面會用到的東西是那些過場畫面效果元件,像是「處理中....」這類的東西,所以今天就小小分享一下實作及效果的差異
(先不說 DisplaySnackBarAsync ,如果你不要自帶動畫的話,這可以直接套用,參考這個影音教學)
先開箱Popup元件,這東西不錯用,日後會非常倚重它,參考以下教學網址
Pass Data From and To Popups with Xamarin Community Toolkit
直接上code
-----ProcessingPopup.xmal--------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<xct:Popup
xmlns="http://xamarin.com/schemas/2014/forms"
<Label x:Name="myLabel" Text="Porcessing......." VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
----ProcessingPopup.xmal.cs------------------
//Clasable介面沒什麼東西,就只有一個DoClose函數罷了
public class PopupResult {
public string ReturnData { get; set; }
}
public partial class ProcessingPopup : Popup<PopupResult>, Closable {
private PopupResult _result;
int count = 1;
bool toLoop = true;
public ProcessingPopup(PopupResult result) {
InitializeComponent();
_result=result;
//順便學會在form裡用執行緒的技巧
//UI thread請參考這裡(楓花雪岳)更詳細說明
Device.BeginInvokeOnMainThread(async () => {
while(toLoop) {
if(count>5)
count=1;
myLabel.Text="Please Wait"+".....".Substring(0, count);
count++;
await Task.Delay(500);
}
//DoClose();
});
}
public async void DoClose() {
toLoop=false;
await Task.Delay(500);
Dismiss(new PopupResult {
ReturnData="Close from Login"
});
}
}
---------------------------------------The caller -- LoginPage.xmal.cs---------------------------
login按鈕事件:
「阿你之前用AndroidHud & BTProgressHUD 很好看啊,怎麼不拿來用? 」...好吧,可是AndroidHud是有點東西要加工的,
原本在Xamarin.Android裡的一堆函數會用到的ActivityContext
如「AndroidHUD.AndHUD.Shared.Show(this,"msg",-1,MaskType.Clear)」這裡面的 this是當下的ActivityContext,移植到Xamarin.Form就是Forms.Context,但是!!!!...
Xamarin.Form 2.5之後就不給用Forms.Context,所以要另外加點工
(討論參考這裡)
經上述討論建議,我直接改了Application那裡....
--------------MainApplication.cs----------------------------------
參考文件,請參考官方範例
https://docs.microsoft.com/zh-tw/xamarin/ios/app-fundamentals/file-system
info.plist需要兩個鍵值,如果光只有「UIFileSharingEnabled」
是無法在你的iphone上面的檔案app裡找到你的app分享出來的檔案的
想要讓iphone的「檔案」app用瀏覽「我的iphone」裡出現你的app icon資料夾(MyDocument).
就要另一個鍵值--「LSSupportsOpeningDocumentsInPlace」了
這篇也是不錯的討論,用模擬器開發的朋友可以參考
可是問題來了,先前你放在MyDocument裡特殊資料(像是json啦、SQLite db啦.....)不就都被看光了?
解決之道就在最初那份文件--把敏感資料搬到MyDocument上層的library裡就是了
(至於用「更新」的方式搭配上述的搬檔,有沒有work,知道的朋友麻煩指導在下一下,謝謝先了)
同場加映:
Xamarin.android的下載目錄在哪?
答案 : Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath
以上,大家加油了
之前到安卓8以後已經有一種寫法了,太煩瑣了,
好在最近又有update了
今天把它記錄下來,以免下次又要找到天窮碧落下黃泉之窘境了
------------------------------------------------------
using Xamarin.Essentials;
...
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
...
}
//-----以下整碗做你捧去,我也是copy改出來的-------
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) {
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
public async Task<Xamarin.Essentials.PermissionStatus> CheckAndRequestPermissionAsync<T>(T permission)
where T : Xamarin.Essentials.Permissions.BasePermission {
var status = await permission.CheckStatusAsync();
if (status != Xamarin.Essentials.PermissionStatus.Granted) {
status = await permission.RequestAsync();
}
return status;
}
//以下以存檔權限為例,請自己改其他權限來用
public async Task ExportToExcelnAsync() {
var status = await CheckAndRequestPermissionAsync(new Xamarin.Essentials.Permissions.StorageWrite());
if (status != Xamarin.Essentials.PermissionStatus.Granted) {
// Notify user permission was denied
return;
}
await 你預訂得到權限後要做的事();
}
//-----Code海無邊,回頭是岸-----
--------------------------------
為什麼要寫出套件全名?因為很不巧一個叫「Plugin」的套件也有類似的權限套件
為了不被混淆,就全名標示了
本文技巧出處參考這裡
PS. 拜託安卓跟蘋果:你們可以不要再改了嗎?每次一版我就要重學,很累的耶,能不能像大話西遊一樣「如果非要在這些架構套件開發技術上加一個期限,我希望是……一萬年」啊
最近應人客的要求,小改界面(layout file),可是build卻出現了「android string types not allowed (at 'background' with value ' ').」而且是在第二行.....
可是明明在xml中第2行也不是background的設定啊...
------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="horizontal">
....
.....
------------------------------------------------------
到底遇到了什麼靈異事件了!? (就算把上述的background行拿掉,re build還是一樣的錯誤訊息)
答案是.....錯誤訊息的「行」是xml reader read 進去時以xml節點去算的,第一行是<?xml versin.....?>
而其他的元素,就算在第二行,如同意大利線條一整條吃進去,,所以在其中任意子節點的錯,都算在第2行裡
所以,就算是把最開頭的LinearLayout裡的background行刪去,只要整個xml檔其他地方有錯,都是出現「第二行出錯」的訊息 (就算是在layout designer看來都對的情況下)
但,好歹知道是background屬性錯了,那就一個一個background屬性去找就對了
好,最有可能是不小心改到的background值.
------------------------------------------
<ImageButton
android:id="@+id/xxxxxxxx"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background=""
/>
----------------------------------
少年仔,background沒咧安呢用的,要嘛就不寫,要不就用"@null" 就是了
(但,如果你有 android:src="@drawable/xxxx" 屬性,卻想設定他去背--支援透明的話,就可以設定「android:background="#00000000"」了)
總之,儘信 IDE不如無IDE啊. Layout designer看到正常的東西,未必就是正確的啊
一起加油囉
明明在IDE中用開發模式連iphone測都正常,以往這樣送審都會過,
沒辦法,現在已經規定iphone & ipad都要過才准上架
這次送審時回報app在ipad中掛了,訊息落落長,總歸這句
"/System/Library/Frameworks/SensorKit.framework/SensorKit' not found"
(當然也包括了明明沒用到Health Kit卻說要你移除的「建議」)
好在一堆人也幫你踢了鐵板了
最主要的就是要把link模式設定為「Link Framework SDKs Only」 (預設是Don't Link)
打包測完確定這樣link模式可以跑(而且test flight成員也測了沒事)
如果Link Framework SDKs Only會掛的話,建議降版--改用sdk 14.4
並修改info.plist版本,從14.x降回13.6
(不管你怎麼改,總而言之就是要確定「Link Framework SDKs Only」能work就是了啦)
大家加油囉
同場加映:
如果在clear project時,遇到以下錯誤
----------------------------------
Clean started...
The build was cancelled because another Xamarin operation is running. Please try again in a moment.
1>Error: The operation could not be completed. 無法指出的錯誤
========== Clean: 0 succeeded, 2 failed, 0 skipped ==========
----------------------------------
請把project unload 再reload回去就可以了
login Line Notify
URL:https://notify-bot.line.me/zh_TW/
選「個人頁面」
環境 XCODE 12.4, IOS14.4
1.參考「https://stackoverflow.com/questions/16868117/uitextview-that-expands-to-text-using-auto-layout」,製作grewing text view 的xib.
(我是直接用xcode interface builder的 Hight Priority & content Hugging Priority那段去做的,畢竟我連swift都還不會)
2.參考「www.dotnetmobile.com/XamariniOS/CreatingCustomView」及「https://docs.microsoft.com/zh-tw/xamarin/ios/user-interface/storyboards/」把這個xib跟c#做連結,
參考結果
ViewGrowingText.cs ViewGrowingText.designer.cs ViewGrowingText.xib
如果你直接把它加入UIViewController去試跑,應該是有這效果.
---sample code----
var TxtTest = UI.ViewGrowingText.Create();
TxtTest.Frame = new CoreGraphics.CGRect(0, 200, View.Frame.Width, 30);
//viewMain是我們在xcode中用outlet指定最底層的view為此UIViewcontroller中的變數成員,基本上跟「View」這個在UIViewController中的變數是同一個東西
viewMain.AddSubview(TxtTest);
viewMain.LayoutIfNeeded();
----------------
-----實驗完記得把這個TxtTest移掉,因為這不是我們要的結果-----
現在,我們在目前的UIViewController底部加一個TextView(或是TextField沒差)名字為「txtMsg2Send」
我們要把個GrowingTextView放到小鍵盤上面,而且要能自已依照灰色TextView加減的高度而自己跟著調整高度,要在操作txtMsg2Send會出現
直接看code吧
------------------------------------------------
nfloat orgHeightOfTxtViewOfInputAccessoryView = 0;
UI.ViewGrowingText inputAccessoryView =null;
UITextView txtViewOfInputAccessoryView =null;
public override void ViewDidLoad() {
base.ViewDidLoad();
if (inputAccessoryView == null) {
inputAccessoryView = UI.ViewGrowingText.Create();
txtViewOfInputAccessoryView = inputAccessoryView.GetTextView();
inputAccessoryView.Frame =
new CoreGraphics.CGRect(0, 0, View.Frame.Width, txtViewOfInputAccessoryView.Frame.Height);
inputAccessoryView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight;
//把這個會長高長壯的GrowingTextView設定為底部的textView的鍵盤工具列
txtMsg2Send.InputAccessoryView = inputAccessoryView;
//先把最初的高度記下來.....
orgHeightOfTxtViewOfInputAccessoryView = txtViewOfInputAccessoryView.Frame.Height;
//重點來了!!文字變時.如何改變inputAccessoryView的高度!?
txtViewOfInputAccessoryView.Changed += (object sender, EventArgs e) => {
var _t = new System.Threading.Thread(new System.Threading.ThreadStart(() => {
InvokeOnMainThread(async () => {
await Task.Delay(50);
//只比較textView高度到小數點三位數
if (Math.Round(txtViewOfInputAccessoryView.Frame.Size.Height, 3, MidpointRounding.AwayFromZero) !=
Math.Round(orgHeightOfTxtViewOfInputAccessoryView, 3, MidpointRounding.AwayFromZero)) {
//高度異動!!調整外層inputAccessoryView的高度
//光是用Frame=....是沒用的,要動到cosntraints裡才會作動!!
orgHeightOfTxtViewOfInputAccessoryView = (float)txtViewOfInputAccessoryView.Frame.Size.Height;
var cst =
inputAccessoryView.Superview.Constraints.Where(Q => Q.Identifier() == "accessoryHeight").FirstOrDefault();
cst.Active = false;
inputAccessoryView.LayoutIfNeeded();
cst.Constant = orgHeightOfTxtViewOfInputAccessoryView;
cst.Active = true;
inputAccessoryView.Superview.AddConstraint(cst);
if (inputAccessoryView.Superview.Superview != null) {
inputAccessoryView.Superview.Superview.LayoutIfNeeded();
}
}
});
}));
_t.Start();
...
...end of ViewDidLoad.....
}
-------------------------------------------------
結果....
是不是愈來愈有專業的樣子了呢?
OS:自從我用了GrowingTextView之後,考試都考一百分,而且人明顯高了、壯了、變得更美了,
上述那段紅字,請參考這裡 我只是把它改成xamarin c# 罷了,懂得真的太少了,真的要花點時間學swift了
另一種作法是在出現小鍵盤時,整個畫面往上捲,配合在UIViewController底部的GrowingText來做到這效果,請參這裡 的keyboard事件處理
哪個好!? 鐘鼎山林,人各有志,攏好啦
大家加油吧
(反正疫情期間哪都不能去,乖乖在家好好寫程式吧)
現在xamarin.ios的xib都只能在xcode之下設計了,著實非常不便
但沒辦法,實在不想用xamarin form 架構,只好認命了
UILabel雖然在xcode interfacebuilder中有「UserInteractionEnabled」設定可以讓你勾,
但,經過實驗,真的,你還是要在code中設定才能listen tap 事件,參考以下
------------------------------------
var tapRecognizer = new UITapGestureRecognizer();
tapRecognizer.AddTarget(() => {
// tap時事件實作
...
...
...
});
lblA.UserInteractionEnabled = true;
tapRecognizer.NumberOfTapsRequired = 1;
lblA.AddGestureRecognizer(tapRecognizer);
-------------------------------------
我書讀不多,不知道原來addTarget是要這樣用(而不是action !?)
anyway,總之,要用AddTarget設定實作,UserInteractionEnabled要設定(雖然我已經在xcode設計階段就指定了,真的,還是要在code設定才行),NumberOfTapsRequired 也要指定,最後加入GestureRecognizer
參考:這裡
一起加油吧.
雖然有過場動畫會比較花俏可愛,但正式/商用app是不喜歡這種玩意兒的
如何取消過場動畫?
兩個指令就可以了
----在某個ativity裡要切換到下個actity的片段----------
Intent itxnNext=
new Intent(this, typeof(下個actity類別的class路徑)).AddFlags(ActivityFlags.NoAnimation);
StartActivity(itxnNext);
OverridePendingTransition(0, 0);
Finish();
-----------------------------------------------
注意!!
OverridePenddingTransition指令一要在StartActivity指令之後,順序一定要對!!
不然你會試不出效果的!!
參考:這裡
一起加油吧
安安,給虧嗎? (會用「安安」的表示這一定是個老網民了)
安安不給虧不要緊,程式不給debug才麻煩吧
今天就是要講這樣一個故事--一個asp.net core web project從他台搬來新的PC
卻一直debug不行,直接結束,clear & rebuild也一樣,明明build都成功啊.....
就某32bit data而言 (ex : *pRccCfg)
經初始化0b0
我們把bit 22設定為1 之後 (by instruction : 「 *pRccCfg|= (1<<22) ; 」)
要把bit 24~26設定為0b110,又不能動到之前設定的其他bit值,如何是好?
作法1.一個bit一個bit設定
*pRccCfg!=(1<<25)
*pRccCfg!=(1<<26)
作法二,用罩除的方式,比較不建議請注意"~"的用法
*pRccCfg!=(7<<24); // "OR" the 3 bits by 0b111
*pRccCfg &=~(1<<24);//shift the bit ,then "Complement them",then,use "AND" opeartion,
------------------------------------------------------------------------
同理,只是想清除某幾個bit,也是先 shift "on" bits ,"Complement them",then ,use "AND"operation
ex:要把21&22 bits清除,但不要動到其他bits,請用以下方式
*pAddrRccCfg &=~(0x3<<21);
務必注意!!
~(0x3<<21) 是
11111111100111111111111111111111
而(~0x3<<21) 是
11111111100000000000000000000000
千萬要注意順序
2.Install WinHttpHandler:
Install-Package System.Net.Http.WinHttpHandler
3.Extend WinHttpHandler to add http2.0 support:
public class Http2CustomHandler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
4.Pass above handler to the HttpClient constructor
using (var httpClient = new HttpClient(new Http2CustomHandler()))
{
// your custom code
}
---------------------------------
(所以就是要用非同步的方式去呼叫了,沒差,用執行緒去做就是了)
雖然案主說你就再申請一個apns 憑證嘛.何必這樣大費周章?
可是每一個憑證每年都要換證,就是怕在換證時uer漏接了重要的訊息
這次一做,日後很多個APP都可以共用,也沒有期限問題,長痛不如短痛啊,根本性地解決問題,不亦快哉?
在xamarin ios經常更新,以往的加解密函數現在出現這現象
----code----
var s = new SecRecord(SecKind.GenericPassword) {
ValueData = NSData.FromString(value),
Generic = NSData.FromString(key),
Invisible = true,
CreationDate = NSDate.Now
};
var err = SecKeyChain.Add(s);
------------------
結果err傳回值是「Security.SecStatusCode.MissingEntitlement」
好在別人已經踢到鐵板了,請參考以下的方式修改
https://forums.xamarin.com/discussion/145357/seckeychain-add-return-security-secstatuscode-missingentitlement
注意,其中的
------------
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)你的appBundle ID</string>
</array>
------------------------------------
紅色字$(AppIdentifierPrefix)要去掉,
這是用vs2019 IOS manifest Editor打開加入keychain選項他自己加上去的
要小心--盡信editor不如無editor
加油!!
安卓開發就怕一直在改版的問題一再發生
最近很多開發者都遇到明明在notification的震動機制好好的,怎麼升級後又惦惦了
google了一下是要加上 audioattribute--
---example-----
audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM) //key
.build();
mVibrator.vibrate(pattern, 1, audioAttributes);
-----------------
來源參考:
https://www.jianshu.com/p/3ec9158b2041
同場加映
有些圓標可以用線上的icon generator來產生
https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html
請多加利用左側功能表中的background color等屬性
https://romannurik.github.io/AndroidAssetStudio/index.html <--這裡還有 notification icon generator可以用哦
(一升級就搞得大家雞飛狗跳的,希望馬斯克的手機系統不會這樣麻煩)
大家加油吧