diff --git a/Billing.Shared/App.cs b/Billing.Shared/App.cs
index dc9cd94..cc0fd7f 100644
--- a/Billing.Shared/App.cs
+++ b/Billing.Shared/App.cs
@@ -13,6 +13,7 @@ namespace Billing
 {
     public class App : Application
     {
+        internal const string NewBillAction = "/newbill";
         private const string SaveLocationKey = nameof(SaveLocationKey);
 
         public static AppTheme CurrentTheme { get; private set; }
@@ -21,17 +22,27 @@ namespace Billing
         public static List<Account> Accounts => accounts ??= new List<Account>();
         public static List<Category> Categories => categories ??= new List<Category>();
         public static bool SaveLocation => saveLocation;
+        public static string MainRoute => mainRoute;
 
         private static List<Bill> bills;
         private static List<Account> accounts;
         private static List<Category> categories;
         private static bool saveLocation;
+        private static string mainRoute;
 
         private string initialUrl;
 
         public App(string url = null)
         {
-            initialUrl = url;
+            if (url == NewBillAction)
+            {
+                mainRoute = "//Bills/Details";
+            }
+            else
+            {
+                mainRoute = "//Bills";
+                initialUrl = url;
+            }
             CurrentCulture = new PlatformCulture();
             InitResources();
 
diff --git a/Billing.Shared/MainShell.xaml.cs b/Billing.Shared/MainShell.xaml.cs
index 8146bcc..d571a06 100644
--- a/Billing.Shared/MainShell.xaml.cs
+++ b/Billing.Shared/MainShell.xaml.cs
@@ -1,3 +1,4 @@
+using Billing.Views;
 using Xamarin.Forms;
 
 namespace Billing
@@ -6,6 +7,8 @@ namespace Billing
     {
         public MainShell()
         {
+            Routing.RegisterRoute("Bills/Details", typeof(AddBillPage));
+
             InitializeComponent();
         }
     }
diff --git a/Billing.Shared/SplashPage.xaml.cs b/Billing.Shared/SplashPage.xaml.cs
index 1533529..0837cb4 100644
--- a/Billing.Shared/SplashPage.xaml.cs
+++ b/Billing.Shared/SplashPage.xaml.cs
@@ -14,7 +14,7 @@ namespace Billing
         {
             await App.InitializeData();
 
-            await Shell.Current.GoToAsync("//Bills");
+            await Shell.Current.GoToAsync(App.MainRoute);
         }
     }
 }
diff --git a/Billing.Shared/Store/StoreHelper.cs b/Billing.Shared/Store/StoreHelper.cs
index 7457b32..c115d50 100644
--- a/Billing.Shared/Store/StoreHelper.cs
+++ b/Billing.Shared/Store/StoreHelper.cs
@@ -38,6 +38,7 @@ namespace Billing.Store
             catch (Exception ex)
             {
                 Helper.Error("database.close", ex);
+                return false;
             }
             try
             {
@@ -54,12 +55,13 @@ namespace Billing.Store
                     SQLiteOpenFlags.ReadWrite |
                     SQLiteOpenFlags.Create |
                     SQLiteOpenFlags.SharedCache);
+                return true;
             }
             catch (Exception ex)
             {
                 Helper.Error("database.connect", ex);
+                return false;
             }
-            return true;
         }
 
         public static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
diff --git a/Billing.Shared/Views/AddBillPage.xaml.cs b/Billing.Shared/Views/AddBillPage.xaml.cs
index 480ace3..6b328ec 100644
--- a/Billing.Shared/Views/AddBillPage.xaml.cs
+++ b/Billing.Shared/Views/AddBillPage.xaml.cs
@@ -70,6 +70,7 @@ namespace Billing.Views
         private CancellationTokenSource tokenSource;
         private Location location;
 
+        public AddBillPage() : this(DateTime.Today) { }
         public AddBillPage(DateTime date)
         {
             createDate = date;
diff --git a/Billing.Shared/Views/RankPage.xaml b/Billing.Shared/Views/RankPage.xaml
index e53e388..7797798 100644
--- a/Billing.Shared/Views/RankPage.xaml
+++ b/Billing.Shared/Views/RankPage.xaml
@@ -13,25 +13,24 @@
                 Shell.TabBarIsVisible="True">
 
     <Shell.TitleView>
-        <StackLayout Orientation="Horizontal" Spacing="10">
+        <Grid ColumnSpacing="10" ColumnDefinitions="30, *, 30">
             <ui:TintImageButton Source="left.png" WidthRequest="20" HeightRequest="20"
-                                VerticalOptions="Center" HorizontalOptions="Start"
+                                VerticalOptions="Center" HorizontalOptions="Center"
                                 Command="{Binding LeftCommand}"/>
-            <Label Text="{Binding Title}"
+            <Label Grid.Column="1" Text="{Binding Title}"
                    TextColor="{DynamicResource PrimaryColor}"
                    FontSize="{OnPlatform Android=20, iOS=18}"
                    FontFamily="{x:Static ui:Definition.SemiBoldFontFamily}"
                    VerticalOptions="Center"
-                   HorizontalOptions="FillAndExpand"
-                   HorizontalTextAlignment="Center">
+                   HorizontalOptions="Center">
                 <Label.GestureRecognizers>
                     <TapGestureRecognizer Command="{Binding FilterCommand}"/>
                 </Label.GestureRecognizers>
             </Label>
-            <ui:TintImageButton Source="right.png" WidthRequest="20" HeightRequest="20"
-                                VerticalOptions="Center" HorizontalOptions="End"
+            <ui:TintImageButton Grid.Column="2" Source="right.png" WidthRequest="20" HeightRequest="20"
+                                VerticalOptions="Center" HorizontalOptions="Center"
                                 Command="{Binding RightCommand}"/>
-        </StackLayout>
+        </Grid>
     </Shell.TitleView>
 
     <!--<ContentPage.ToolbarItems>
diff --git a/Billing/Billing.Android/Billing.Android.csproj b/Billing/Billing.Android/Billing.Android.csproj
index 9a73377..e18038b 100644
--- a/Billing/Billing.Android/Billing.Android.csproj
+++ b/Billing/Billing.Android/Billing.Android.csproj
@@ -607,7 +607,9 @@
   <ItemGroup>
     <AndroidResource Include="Resources\drawable\left.png" />
   </ItemGroup>
-  <ItemGroup />
+  <ItemGroup>
+    <AndroidResource Include="Resources\xml\shortcuts.xml" />
+  </ItemGroup>
   <Import Project="..\..\Billing.Shared\Billing.Shared.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/Billing/Billing.Android/MainActivity.cs b/Billing/Billing.Android/MainActivity.cs
index edb5074..69f75be 100644
--- a/Billing/Billing.Android/MainActivity.cs
+++ b/Billing/Billing.Android/MainActivity.cs
@@ -4,7 +4,6 @@ using Android.Content.PM;
 using Android.Runtime;
 using Android.OS;
 using Android.Net;
-using System.Collections.Generic;
 using Android.Provider;
 using Android.Database;
 
@@ -26,7 +25,14 @@ namespace Billing.Droid
             string url;
             if (Intent.ActionView.Equals(Intent.Action) && Intent.Data is Uri uri)
             {
-                url = GetFilePath(BaseContext, uri);
+                if (uri.Authority == "org.tsanie.billing.shortcuts")
+                {
+                    url = uri.Path;
+                }
+                else
+                {
+                    url = GetFilePath(BaseContext, uri);
+                }
             }
             else
             {
@@ -82,6 +88,15 @@ namespace Billing.Droid
             }
             else if (uri.Scheme == "content")
             {
+                if (uri.Authority == "com.speedsoftware.rootexplorer.fileprovider")
+                {
+                    var path = uri.Path;
+                    if (path.StartsWith("/root/"))
+                    {
+                        return path[5..];
+                    }
+                    return path;
+                }
                 return GetDataColumn(context, uri, null, null);
             }
             else if (uri.Scheme == "file")
diff --git a/Billing/Billing.Android/Properties/AndroidManifest.xml b/Billing/Billing.Android/Properties/AndroidManifest.xml
index a984595..9bd9c43 100644
--- a/Billing/Billing.Android/Properties/AndroidManifest.xml
+++ b/Billing/Billing.Android/Properties/AndroidManifest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.2.317" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="16">
 	<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
-	<application android:label="@string/applabel" android:theme="@style/MainTheme"></application>
+	<application android:label="@string/applabel" android:theme="@style/MainTheme" android:requestLegacyExternalStorage="true"></application>
 	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 	<queries>
 		<intent>
diff --git a/Billing/Billing.Android/Resources/Resource.designer.cs b/Billing/Billing.Android/Resources/Resource.designer.cs
index f81d669..08a693c 100644
--- a/Billing/Billing.Android/Resources/Resource.designer.cs
+++ b/Billing/Billing.Android/Resources/Resource.designer.cs
@@ -14,7 +14,7 @@ namespace Billing.Droid
 {
 	
 	
-	[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+	[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "12.2.0.155")]
 	public partial class Resource
 	{
 		
@@ -21803,43 +21803,46 @@ namespace Billing.Droid
 			public const int nav_app_bar_open_drawer_description = 2131624042;
 			
 			// aapt resource value: 0x7F0E006B
-			public const int not_set = 2131624043;
+			public const int newbill = 2131624043;
 			
 			// aapt resource value: 0x7F0E006C
-			public const int overflow_tab_title = 2131624044;
+			public const int not_set = 2131624044;
 			
 			// aapt resource value: 0x7F0E006D
-			public const int password_toggle_content_description = 2131624045;
+			public const int overflow_tab_title = 2131624045;
 			
 			// aapt resource value: 0x7F0E006E
-			public const int path_password_eye = 2131624046;
+			public const int password_toggle_content_description = 2131624046;
 			
 			// aapt resource value: 0x7F0E006F
-			public const int path_password_eye_mask_strike_through = 2131624047;
+			public const int path_password_eye = 2131624047;
 			
 			// aapt resource value: 0x7F0E0070
-			public const int path_password_eye_mask_visible = 2131624048;
+			public const int path_password_eye_mask_strike_through = 2131624048;
 			
 			// aapt resource value: 0x7F0E0071
-			public const int path_password_strike_through = 2131624049;
+			public const int path_password_eye_mask_visible = 2131624049;
 			
 			// aapt resource value: 0x7F0E0072
-			public const int preference_copied = 2131624050;
+			public const int path_password_strike_through = 2131624050;
 			
 			// aapt resource value: 0x7F0E0073
-			public const int search_menu_title = 2131624051;
+			public const int preference_copied = 2131624051;
 			
 			// aapt resource value: 0x7F0E0074
-			public const int status_bar_notification_info_overflow = 2131624052;
+			public const int search_menu_title = 2131624052;
 			
 			// aapt resource value: 0x7F0E0075
-			public const int summary_collapsed_preference_list = 2131624053;
+			public const int status_bar_notification_info_overflow = 2131624053;
 			
 			// aapt resource value: 0x7F0E0076
-			public const int v7_preference_off = 2131624054;
+			public const int summary_collapsed_preference_list = 2131624054;
 			
 			// aapt resource value: 0x7F0E0077
-			public const int v7_preference_on = 2131624055;
+			public const int v7_preference_off = 2131624055;
+			
+			// aapt resource value: 0x7F0E0078
+			public const int v7_preference_on = 2131624056;
 			
 			static String()
 			{
@@ -32297,22 +32300,25 @@ namespace Billing.Droid
 			public const int image_share_filepaths = 2131820544;
 			
 			// aapt resource value: 0x7F110001
-			public const int standalone_badge = 2131820545;
+			public const int shortcuts = 2131820545;
 			
 			// aapt resource value: 0x7F110002
-			public const int standalone_badge_gravity_bottom_end = 2131820546;
+			public const int standalone_badge = 2131820546;
 			
 			// aapt resource value: 0x7F110003
-			public const int standalone_badge_gravity_bottom_start = 2131820547;
+			public const int standalone_badge_gravity_bottom_end = 2131820547;
 			
 			// aapt resource value: 0x7F110004
-			public const int standalone_badge_gravity_top_start = 2131820548;
+			public const int standalone_badge_gravity_bottom_start = 2131820548;
 			
 			// aapt resource value: 0x7F110005
-			public const int standalone_badge_offset = 2131820549;
+			public const int standalone_badge_gravity_top_start = 2131820549;
 			
 			// aapt resource value: 0x7F110006
-			public const int xamarin_essentials_fileprovider_file_paths = 2131820550;
+			public const int standalone_badge_offset = 2131820550;
+			
+			// aapt resource value: 0x7F110007
+			public const int xamarin_essentials_fileprovider_file_paths = 2131820551;
 			
 			static Xml()
 			{
diff --git a/Billing/Billing.Android/Resources/values-zh-rCN/strings.xml b/Billing/Billing.Android/Resources/values-zh-rCN/strings.xml
index 25b7ec0..2273f6d 100644
--- a/Billing/Billing.Android/Resources/values-zh-rCN/strings.xml
+++ b/Billing/Billing.Android/Resources/values-zh-rCN/strings.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <resources>
     <string name="applabel">记账本</string>
+    <string name="newbill">记录一条</string>
 </resources>
\ No newline at end of file
diff --git a/Billing/Billing.Android/Resources/values/strings.xml b/Billing/Billing.Android/Resources/values/strings.xml
index d70d42c..ac2b1dd 100644
--- a/Billing/Billing.Android/Resources/values/strings.xml
+++ b/Billing/Billing.Android/Resources/values/strings.xml
@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <resources>
     <string name="applabel">Billing</string>
+    <string name="newbill">Write a bill</string>
 </resources>
\ No newline at end of file
diff --git a/Billing/Billing.Android/Resources/xml/shortcuts.xml b/Billing/Billing.Android/Resources/xml/shortcuts.xml
new file mode 100644
index 0000000..43f9856
--- /dev/null
+++ b/Billing/Billing.Android/Resources/xml/shortcuts.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
+	<shortcut android:shortcutId="newbill" android:enabled="true" android:icon="@drawable/daily" android:shortcutShortLabel="@string/newbill" android:shortcutLongLabel="@string/newbill" android:shortcutDisabledMessage="@string/newbill">
+		<intent android:action="android.intent.action.VIEW" android:targetPackage="org.tsanie.billing" android:targetClass="org.tsanie.billing.SplashScreen" android:data="content://org.tsanie.billing.shortcuts/newbill" />
+	</shortcut>
+</shortcuts>
\ No newline at end of file
diff --git a/Billing/Billing.Android/SplashActivity.cs b/Billing/Billing.Android/SplashActivity.cs
index 354a998..a6c9ea0 100644
--- a/Billing/Billing.Android/SplashActivity.cs
+++ b/Billing/Billing.Android/SplashActivity.cs
@@ -18,6 +18,9 @@ namespace Billing.Droid
         //DataScheme = "file",
         DataMimeType = "*/*",
         DataPathPattern = ".*\\.db3")]
+    [MetaData(
+        "android.app.shortcuts",
+        Resource = "@xml/shortcuts")]
     public class SplashActivity : AppCompatActivity
     {
         public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
diff --git a/Billing/Billing.iOS/AppDelegate.cs b/Billing/Billing.iOS/AppDelegate.cs
index 2e73242..02fb032 100644
--- a/Billing/Billing.iOS/AppDelegate.cs
+++ b/Billing/Billing.iOS/AppDelegate.cs
@@ -1,4 +1,5 @@
 using Foundation;
+using ObjCRuntime;
 using UIKit;
 
 namespace Billing.iOS
@@ -19,7 +20,16 @@ namespace Billing.iOS
         public override bool FinishedLaunching(UIApplication app, NSDictionary options)
         {
             Xamarin.Forms.Forms.Init();
-            LoadApplication(new App());
+            string action;
+            if (options != null && options.TryGetValue(UIApplication.LaunchOptionsShortcutItemKey, out var obj) && obj is UIApplicationShortcutItem shortcut)
+            {
+                action = "/" + shortcut.Type;
+            }
+            else
+            {
+                action = null;
+            }
+            LoadApplication(new App(action));
 
             return base.FinishedLaunching(app, options);
         }
@@ -32,5 +42,14 @@ namespace Billing.iOS
             }
             return false;
         }
+
+        public override void PerformActionForShortcutItem(UIApplication application, UIApplicationShortcutItem shortcutItem, UIOperationHandler completionHandler)
+        {
+            if (shortcutItem == null || string.IsNullOrEmpty(shortcutItem.Type))
+            {
+                return;
+            }
+            Xamarin.Essentials.MainThread.BeginInvokeOnMainThread(async () => await Xamarin.Forms.Shell.Current.GoToAsync("//Bills/Details"));
+        }
     }
 }
\ No newline at end of file
diff --git a/Billing/Billing.iOS/Base.lproj/InfoPlist.strings b/Billing/Billing.iOS/Base.lproj/InfoPlist.strings
index 19f66b9..66d1434 100644
--- a/Billing/Billing.iOS/Base.lproj/InfoPlist.strings
+++ b/Billing/Billing.iOS/Base.lproj/InfoPlist.strings
@@ -1,2 +1,3 @@
 "CFBundleDisplayName" = "Billing";
+"BillingShortcutNew" = "Write a bill";
 "NSLocationWhenInUseUsageDescription" = "When &quot;Save Location&quot; is checked, the Billing app needs to access the location.";
\ No newline at end of file
diff --git a/Billing/Billing.iOS/Info.plist b/Billing/Billing.iOS/Info.plist
index dce218b..8d34333 100644
--- a/Billing/Billing.iOS/Info.plist
+++ b/Billing/Billing.iOS/Info.plist
@@ -93,5 +93,16 @@
 	<true/>
 	<key>NSLocationWhenInUseUsageDescription</key>
 	<string>When &quot;Save Location&quot; is checked, the Billing app needs to access the location.</string>
+	<key>UIApplicationShortcutItems</key>
+	<array>
+		<dict>
+			<key>UIApplicationShortcutItemIconType</key>
+			<string>UIApplicationShortcutIconTypeCompose</string>
+			<key>UIApplicationShortcutItemTitle</key>
+			<string>BillingShortcutNew</string>
+			<key>UIApplicationShortcutItemType</key>
+			<string>newbill</string>
+		</dict>
+	</array>
 </dict>
 </plist>
diff --git a/Billing/Billing.iOS/zh-Hans.lproj/InfoPlist.strings b/Billing/Billing.iOS/zh-Hans.lproj/InfoPlist.strings
index e009fa3..f8e70c2 100644
--- a/Billing/Billing.iOS/zh-Hans.lproj/InfoPlist.strings
+++ b/Billing/Billing.iOS/zh-Hans.lproj/InfoPlist.strings
@@ -1,2 +1,3 @@
 "CFBundleDisplayName" = "记账本";
+"BillingShortcutNew" = "记录一条";
 "NSLocationWhenInUseUsageDescription" = "当选中“保存位置”时,记账本需要访问位置信息。";
\ No newline at end of file