Almost done app
@@ -0,0 +1,19 @@
|
||||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories) and given a Build Action of "AndroidAsset".
|
||||
|
||||
These files will be deployed with your package and will be accessible using Android's
|
||||
AssetManager, like this:
|
||||
|
||||
public class ReadAsset : Activity
|
||||
{
|
||||
protected override void OnCreate (Bundle bundle)
|
||||
{
|
||||
base.OnCreate (bundle);
|
||||
|
||||
InputStream input = Assets.Open ("my_asset.txt");
|
||||
}
|
||||
}
|
||||
|
||||
Additionally, some Android functions will automatically load asset files:
|
||||
|
||||
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Database;
|
||||
using Android.Provider;
|
||||
using Android.Support.V4.Content;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Calendar
|
||||
{
|
||||
public static void LoadCalendars()
|
||||
{
|
||||
Data.Calendars = new List<(string, string)>();
|
||||
|
||||
var calendarsUri = CalendarContract.Calendars.ContentUri;
|
||||
string[] calendarsProjection = {
|
||||
CalendarContract.Calendars.InterfaceConsts.Id,
|
||||
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
|
||||
CalendarContract.Calendars.InterfaceConsts.AccountName,
|
||||
CalendarContract.Calendars.InterfaceConsts.OwnerAccount,
|
||||
CalendarContract.Calendars.InterfaceConsts.AccountType,
|
||||
};
|
||||
|
||||
using CursorLoader loader = new CursorLoader(Application.Context, calendarsUri, calendarsProjection, null, null, null);
|
||||
ICursor cursor = (ICursor)loader.LoadInBackground();
|
||||
|
||||
cursor.MoveToNext();
|
||||
for (int i = 0; i < cursor.Count; i++)
|
||||
{
|
||||
if (cursor.GetString(4) == "com.google" && !cursor.GetString(3).Contains("google"))
|
||||
Data.Calendars.Add((cursor.GetString(0), $"{cursor.GetString(1)} ({cursor.GetString(2)})"));
|
||||
cursor.MoveToNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Data
|
||||
{
|
||||
public static List<(string Id, string Name)> Faculties { get; set; }
|
||||
public static List<(string Id, string Name)> Groups { get; set; }
|
||||
public static List<(string Id, string Name)> Calendars { get; set; }
|
||||
public static DateTime StartDate { get; set; } = DateTime.Today;
|
||||
public static DateTime EndDate { get; set; } = DateTime.Today.AddDays(7);
|
||||
|
||||
public static (int faculty, int group, int calendar, int reminder) ExportData { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
using Android.Support.V4.App;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public class DatePickerFragment : DialogFragment, Android.App.DatePickerDialog.IOnDateSetListener
|
||||
{
|
||||
DateTime date;
|
||||
bool dismissed = false;
|
||||
public override Android.App.Dialog OnCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
DateTime now = DateTime.Today;
|
||||
return new Android.App.DatePickerDialog(Activity, this, now.Year, now.Month - 1, now.Day);
|
||||
}
|
||||
|
||||
public void OnDateSet(DatePicker view, int year, int month, int dayOfMonth)
|
||||
{
|
||||
SetDate(view.DateTime);
|
||||
}
|
||||
|
||||
public async Task<DateTime> GetDate(FragmentManager manager, string tag)
|
||||
{
|
||||
Show(manager, tag);
|
||||
|
||||
while (!dismissed)
|
||||
await Task.Delay(500);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
private void SetDate(DateTime date)
|
||||
{
|
||||
this.date = date;
|
||||
dismissed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Android.App;
|
||||
using Android.OS;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
[Activity(Theme = "@style/AppTheme.NoActionBar")]
|
||||
public class ExportActivity : Activity
|
||||
{
|
||||
protected override async void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.export_progress);
|
||||
|
||||
await Task.Delay(5000);
|
||||
|
||||
base.OnBackPressed();
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static void SetList<T>(this Spinner spinner, Context context, IEnumerable<T> array)
|
||||
{
|
||||
ArrayAdapter adapter = new ArrayAdapter(context, Resource.Layout.support_simple_spinner_dropdown_item, array.ToList());
|
||||
spinner.Adapter = adapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{A0471165-37F5-4309-8A92-42F1A6589EEE}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TemplateGuid>{84dd83c5-0fe3-4294-9419-09e7c8ba324f}</TemplateGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GUT.Schedule</RootNamespace>
|
||||
<AssemblyName>GUT.Schedule</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AndroidApplication>True</AndroidApplication>
|
||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||
<AndroidUseAapt2>true</AndroidUseAapt2>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Calendar.cs" />
|
||||
<Compile Include="Data.cs" />
|
||||
<Compile Include="DatePickerFragment.cs" />
|
||||
<Compile Include="ExportActivity.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="Parser.cs" />
|
||||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StartActivity.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\AboutResources.txt" />
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
<None Include="Assets\AboutAssets.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\activity_main.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\values\colors.xml" />
|
||||
<AndroidResource Include="Resources\values\ic_launcher_background.xml" />
|
||||
<AndroidResource Include="Resources\values\styles.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher_round.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\drawable\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Net.Http">
|
||||
<Version>4.3.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Android.Support.Design" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="28.0.0.3" />
|
||||
<PackageReference Include="Xamarin.Essentials" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\splash_screen.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\menu\menu_main.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\export_progress.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Support.Design.Widget;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
[Activity(Theme = "@style/AppTheme")]
|
||||
public class MainActivity : AppCompatActivity
|
||||
{
|
||||
Button start, end, export;
|
||||
Spinner faculty, course, group, reminder, calendar;
|
||||
CheckBox groupTitle;
|
||||
TextView error;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
SetContentView(Resource.Layout.activity_main);
|
||||
|
||||
AssignVariables();
|
||||
AddEvents();
|
||||
|
||||
faculty.SetList(this, Data.Faculties.Select(i => i.Name));
|
||||
course.SetList(this, "12345".ToCharArray());
|
||||
|
||||
reminder.SetList(this, new string[]
|
||||
{
|
||||
"Нет",
|
||||
"Во время начала",
|
||||
"За 5 мин",
|
||||
"За 10 мин"
|
||||
});
|
||||
calendar.SetList(this, Data.Calendars.Select(i => i.Name));
|
||||
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
}
|
||||
|
||||
public override bool OnCreateOptionsMenu(IMenu menu)
|
||||
{
|
||||
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnOptionsItemSelected(IMenuItem item)
|
||||
{
|
||||
int id = item.ItemId;
|
||||
if (id == Resource.Id.github)
|
||||
{
|
||||
StartActivity(new Intent(Intent.ActionView, Android.Net.Uri.Parse("https://github.com/xfox111/GUTSchedule")));
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void Export_Click(object sender, EventArgs e)
|
||||
{
|
||||
error.Visibility = ViewStates.Gone;
|
||||
|
||||
if (Data.StartDate > Data.EndDate)
|
||||
{
|
||||
error.Text = "Ошибка: Неправильный диапазон дат";
|
||||
error.Visibility = ViewStates.Visible;
|
||||
}
|
||||
|
||||
|
||||
StartActivity(new Intent(this, typeof(ExportActivity)));
|
||||
}
|
||||
|
||||
private async void End_Click(object sender, EventArgs e)
|
||||
{
|
||||
DatePickerFragment picker = new DatePickerFragment();
|
||||
Data.EndDate = await picker.GetDate(SupportFragmentManager, "datePicker");
|
||||
end.Text = Data.EndDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void Start_Click(object sender, EventArgs e)
|
||||
{
|
||||
DatePickerFragment picker = new DatePickerFragment();
|
||||
Data.StartDate = await picker.GetDate(SupportFragmentManager, "datePicker");
|
||||
start.Text = Data.StartDate.ToShortDateString();
|
||||
}
|
||||
|
||||
private async void UpdateGroupsList(object sender, AdapterView.ItemSelectedEventArgs e)
|
||||
{
|
||||
if (course.SelectedItem == null)
|
||||
return;
|
||||
|
||||
await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1);
|
||||
group.SetList(this, Data.Groups.Select(i => i.Name));
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { }
|
||||
|
||||
#region Init stuff
|
||||
private void AssignVariables()
|
||||
{
|
||||
start = FindViewById<Button>(Resource.Id.start);
|
||||
end = FindViewById<Button>(Resource.Id.end);
|
||||
export = FindViewById<Button>(Resource.Id.export);
|
||||
|
||||
faculty = FindViewById<Spinner>(Resource.Id.faculty);
|
||||
course = FindViewById<Spinner>(Resource.Id.course);
|
||||
group = FindViewById<Spinner>(Resource.Id.group);
|
||||
reminder = FindViewById<Spinner>(Resource.Id.reminder);
|
||||
calendar = FindViewById<Spinner>(Resource.Id.calendar);
|
||||
|
||||
error = FindViewById<TextView>(Resource.Id.error);
|
||||
}
|
||||
|
||||
private void AddEvents()
|
||||
{
|
||||
faculty.ItemSelected += UpdateGroupsList;
|
||||
course.ItemSelected += UpdateGroupsList;
|
||||
|
||||
start.Click += Start_Click;
|
||||
end.Click += End_Click;
|
||||
|
||||
export.Click += Export_Click;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
public static class Parser
|
||||
{
|
||||
public static async Task LoadFaculties()
|
||||
{
|
||||
Data.Faculties = new List<(string, string)>();
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", "0" },
|
||||
{ "type_z", "1" },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Faculties.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static async Task LoadGroups(string facultyId, int course)
|
||||
{
|
||||
Data.Groups = new List<(string, string)>();
|
||||
using HttpClient client = new HttpClient();
|
||||
Dictionary<string, string> requestBody = new Dictionary<string, string>
|
||||
{
|
||||
{ "choice", "1" },
|
||||
{ "kurs", course.ToString() },
|
||||
{ "type_z", "1" },
|
||||
{ "faculty", facultyId },
|
||||
{ "schet", GetCurrentSemester() }
|
||||
};
|
||||
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabinet.sut.ru/raspisanie_all_new.php")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(requestBody)
|
||||
};
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
|
||||
|
||||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
foreach (string s in responseBody.Split(';'))
|
||||
try { Data.Groups.Add((s.Split(',')[0], s.Split(',')[1])); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
static string GetCurrentSemester()
|
||||
{
|
||||
DateTime now = DateTime.Today;
|
||||
|
||||
if (now.Month > 8)
|
||||
return $"205.{now.Year - 2000}{now.Year - 1999}/1";
|
||||
else
|
||||
return $"205.{now.Year - 2001}{now.Year - 2000}/2";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.xfox111.gut.schedule" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28" />
|
||||
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="ГУТ.Расписание" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBar"></application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
|
||||
</manifest>
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("GUT.Schedule")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GUT.Schedule")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,44 @@
|
||||
Images, layout descriptions, binary blobs and string dictionaries can be included
|
||||
in your application as resource files. Various Android APIs are designed to
|
||||
operate on the resource IDs instead of dealing with images, strings or binary blobs
|
||||
directly.
|
||||
|
||||
For example, a sample Android app that contains a user interface layout (main.xml),
|
||||
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
|
||||
would keep its resources in the "Resources" directory of the application:
|
||||
|
||||
Resources/
|
||||
drawable/
|
||||
icon.png
|
||||
|
||||
layout/
|
||||
main.xml
|
||||
|
||||
values/
|
||||
strings.xml
|
||||
|
||||
In order to get the build system to recognize Android resources, set the build action to
|
||||
"AndroidResource". The native Android APIs do not operate directly with filenames, but
|
||||
instead operate on resource IDs. When you compile an Android application that uses resources,
|
||||
the build system will package the resources for distribution and generate a class called "R"
|
||||
(this is an Android convention) that contains the tokens for each one of the resources
|
||||
included. For example, for the above Resources layout, this is what the R class would expose:
|
||||
|
||||
public class R {
|
||||
public class drawable {
|
||||
public const int icon = 0x123;
|
||||
}
|
||||
|
||||
public class layout {
|
||||
public const int main = 0x456;
|
||||
}
|
||||
|
||||
public class strings {
|
||||
public const int first_string = 0xabc;
|
||||
public const int second_string = 0xbcd;
|
||||
}
|
||||
}
|
||||
|
||||
You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
|
||||
to reference the layout/main.xml file, or R.strings.first_string to reference the first
|
||||
string in the dictionary file values/strings.xml.
|
||||
@@ -0,0 +1,135 @@
|
||||
<?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"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Параметры расписания"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Факультет"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/faculty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Курс"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/course"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Группа"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Параметры экспорта"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Диапазон экспорта"/>
|
||||
|
||||
<TableLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:stretchColumns="*"
|
||||
android:shrinkColumns="*">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/start"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="20-Dec-2019"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="31-Dec-2019"/>
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Напоминать за"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/reminder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/groupTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Добавлять номер группы в заголовок"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Конечный календарь"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/calendar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FF0000"
|
||||
android:text="Error"
|
||||
android:layout_marginVertical="5dp"
|
||||
android:visibility="gone"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/export"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Добавить расписание"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="©2019 Михаил Гордеев ИКСС, ИКТ-907"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Задонатить: +7 (996) 929-19-69 (Сбербанк)"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:indeterminateTint="#fff"
|
||||
android:layout_gravity="fill_horizontal"
|
||||
android:layout_margin="20dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Загрузка"
|
||||
android:textColor="#fff"
|
||||
android:layout_gravity="center_horizontal"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,34 @@
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_centerInParent="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="150dp"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="50dp"
|
||||
android:indeterminateTint="#ffffff"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="Инициализация"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,9 @@
|
||||
<menu 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">
|
||||
<item
|
||||
android:id="@+id/github"
|
||||
android:orderInCategory="100"
|
||||
android:title="Посмотреть исходный код на GitHub"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 958 B |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#ff8000</color>
|
||||
<color name="colorPrimaryDark">#ff8000</color>
|
||||
<color name="colorAccent">#ff8000</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#ff8000</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
<resources>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="android:navigationBarColor">#00000000</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:navigationBarColor">#ff8000</item>
|
||||
<item name="android:windowLightNavigationBar">false</item>
|
||||
<item name="android:windowBackground">@color/colorPrimary</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,79 @@
|
||||
using Android;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Support.V4.Content;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Widget;
|
||||
using System.Linq;
|
||||
|
||||
namespace GUT.Schedule
|
||||
{
|
||||
[Activity(MainLauncher = true, Theme = "@style/AppTheme.NoActionBar")]
|
||||
public class StartActivity : AppCompatActivity
|
||||
{
|
||||
TextView status;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
SetContentView(Resource.Layout.splash_screen);
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
status = FindViewById<TextView>(Resource.Id.status);
|
||||
|
||||
status.Text = "Проверка наличия разрешений";
|
||||
|
||||
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteCalendar) != Permission.Granted)
|
||||
{
|
||||
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.WriteCalendar))
|
||||
ShowDialog();
|
||||
else
|
||||
RequestPermissions();
|
||||
}
|
||||
else
|
||||
Proceed();
|
||||
}
|
||||
|
||||
private async void Proceed()
|
||||
{
|
||||
status.Text = "Загрузка списка доступных для записи календарей";
|
||||
Calendar.LoadCalendars();
|
||||
|
||||
status.Text = "Загрузка списка факультетов";
|
||||
await Parser.LoadFaculties();
|
||||
|
||||
StartActivity(new Intent(this, typeof(MainActivity)));
|
||||
}
|
||||
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
|
||||
{
|
||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (grantResults.All(i => i == Permission.Granted))
|
||||
Proceed();
|
||||
else
|
||||
ShowDialog();
|
||||
}
|
||||
|
||||
private void RequestPermissions() =>
|
||||
ActivityCompat.RequestPermissions(this, new string[]
|
||||
{
|
||||
Manifest.Permission.ReadCalendar, Manifest.Permission.WriteCalendar
|
||||
}, 76);
|
||||
|
||||
private void ShowDialog()
|
||||
{
|
||||
Android.Support.V7.App.AlertDialog.Builder builder = new Android.Support.V7.App.AlertDialog.Builder(this);
|
||||
builder.SetMessage("Разрешите приложению получать доступ к календарю. Без этого разрешения приложение не сможет добавлять расписание в ваш календарь")
|
||||
.SetTitle("Доступ к календарю")
|
||||
.SetPositiveButton("ОК", (s, e) => RequestPermissions());
|
||||
|
||||
Android.Support.V7.App.AlertDialog dialog = builder.Create();
|
||||
dialog.Show();
|
||||
}
|
||||
|
||||
public override void OnBackPressed() { }
|
||||
}
|
||||
}
|
||||