Skip to content
This repository was archived by the owner on Nov 5, 2020. It is now read-only.

Commit 1103738

Browse files
committed
feat: 教务处登录
1 parent 2d4a69b commit 1103738

File tree

9 files changed

+532
-3
lines changed

9 files changed

+532
-3
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ dependencies {
3333
implementation 'com.github.medyo:android-about-page:1.2.4'
3434
implementation 'com.android.support:recyclerview-v7:26.1.0'
3535
implementation 'com.android.support:cardview-v7:22.2.0'
36+
implementation 'com.google.code.gson:gson:2.8.5'
3637
}

app/src/main/AndroidManifest.xml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
<!-- To access Google+ APIs: -->
66
<uses-permission android:name="android.permission.INTERNET" />
77

8+
<!-- To auto-complete the email text field in the login form with the user's emails -->
9+
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
10+
<uses-permission android:name="android.permission.READ_PROFILE" />
11+
<uses-permission android:name="android.permission.READ_CONTACTS" />
12+
813
<application
914
android:allowBackup="true"
1015
android:icon="@mipmap/ic_launcher"
@@ -14,16 +19,17 @@
1419
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
1520
<activity
1621
android:name=".MyWelcomeActivity"
17-
android:theme="@style/WelcomeScreenTheme">
18-
19-
</activity>
22+
android:theme="@style/WelcomeScreenTheme"></activity>
2023
<activity android:name=".MainActivity">
2124
<intent-filter>
2225
<action android:name="android.intent.action.MAIN" />
2326

2427
<category android:name="android.intent.category.LAUNCHER" />
2528
</intent-filter>
2629
</activity>
30+
<activity
31+
android:name=".LoginActivity"
32+
android:label="@string/title_activity_login"></activity>
2733
</application>
2834

2935
</manifest>
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
package io.github.zhaoqi99.snnu_android;
2+
3+
import android.animation.Animator;
4+
import android.animation.AnimatorListenerAdapter;
5+
import android.annotation.TargetApi;
6+
import android.content.pm.PackageManager;
7+
import android.support.annotation.NonNull;
8+
import android.support.design.widget.Snackbar;
9+
import android.support.v7.app.AppCompatActivity;
10+
import android.app.LoaderManager.LoaderCallbacks;
11+
12+
import android.content.CursorLoader;
13+
import android.content.Loader;
14+
import android.database.Cursor;
15+
import android.net.Uri;
16+
import android.os.AsyncTask;
17+
18+
import android.os.Build;
19+
import android.os.Bundle;
20+
import android.provider.ContactsContract;
21+
import android.text.TextUtils;
22+
import android.util.Log;
23+
import android.view.KeyEvent;
24+
import android.view.View;
25+
import android.view.View.OnClickListener;
26+
import android.view.inputmethod.EditorInfo;
27+
import android.widget.ArrayAdapter;
28+
import android.widget.AutoCompleteTextView;
29+
import android.widget.Button;
30+
import android.widget.EditText;
31+
import android.widget.TextView;
32+
import android.widget.Toast;
33+
34+
import com.google.gson.Gson;
35+
import com.google.gson.GsonBuilder;
36+
37+
import java.io.ByteArrayOutputStream;
38+
import java.io.InputStream;
39+
import java.net.HttpURLConnection;
40+
import java.net.URL;
41+
import java.util.ArrayList;
42+
import java.util.List;
43+
44+
import static android.Manifest.permission.READ_CONTACTS;
45+
46+
/**
47+
* A login screen that offers login via email/password.
48+
*/
49+
public class LoginActivity extends AppCompatActivity implements LoaderCallbacks<Cursor> {
50+
51+
/**
52+
* Id to identity READ_CONTACTS permission request.
53+
*/
54+
private static final int REQUEST_READ_CONTACTS = 0;
55+
56+
/**
57+
* A dummy authentication store containing known user names and passwords.
58+
* TODO: remove after connecting to a real authentication system.
59+
*/
60+
private static final String[] DUMMY_CREDENTIALS = new String[]{
61+
62+
};
63+
/**
64+
* Keep track of the login task to ensure we can cancel it if requested.
65+
*/
66+
private UserLoginTask mAuthTask = null;
67+
68+
// UI references.
69+
private AutoCompleteTextView mEmailView;
70+
private EditText mPasswordView;
71+
private View mProgressView;
72+
private View mLoginFormView;
73+
74+
@Override
75+
protected void onCreate(Bundle savedInstanceState) {
76+
super.onCreate(savedInstanceState);
77+
setContentView(R.layout.activity_login);
78+
// Set up the login form.
79+
mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
80+
populateAutoComplete();
81+
82+
mPasswordView = (EditText) findViewById(R.id.password);
83+
mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
84+
@Override
85+
public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
86+
if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
87+
attemptLogin();
88+
return true;
89+
}
90+
return false;
91+
}
92+
});
93+
94+
Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
95+
mEmailSignInButton.setOnClickListener(new OnClickListener() {
96+
@Override
97+
public void onClick(View view) {
98+
attemptLogin();
99+
}
100+
});
101+
102+
mLoginFormView = findViewById(R.id.login_form);
103+
mProgressView = findViewById(R.id.login_progress);
104+
}
105+
106+
private void populateAutoComplete() {
107+
if (!mayRequestContacts()) {
108+
return;
109+
}
110+
111+
getLoaderManager().initLoader(0, null, this);
112+
}
113+
114+
private boolean mayRequestContacts() {
115+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
116+
return true;
117+
}
118+
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
119+
return true;
120+
}
121+
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
122+
Snackbar.make(mEmailView, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
123+
.setAction(android.R.string.ok, new View.OnClickListener() {
124+
@Override
125+
@TargetApi(Build.VERSION_CODES.M)
126+
public void onClick(View v) {
127+
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
128+
}
129+
});
130+
} else {
131+
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
132+
}
133+
return false;
134+
}
135+
136+
/**
137+
* Callback received when a permissions request has been completed.
138+
*/
139+
@Override
140+
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
141+
@NonNull int[] grantResults) {
142+
if (requestCode == REQUEST_READ_CONTACTS) {
143+
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
144+
populateAutoComplete();
145+
}
146+
}
147+
}
148+
149+
150+
/**
151+
* Attempts to sign in or register the account specified by the login form.
152+
* If there are form errors (invalid email, missing fields, etc.), the
153+
* errors are presented and no actual login attempt is made.
154+
*/
155+
private void attemptLogin() {
156+
if (mAuthTask != null) {
157+
return;
158+
}
159+
160+
// Reset errors.
161+
mEmailView.setError(null);
162+
mPasswordView.setError(null);
163+
164+
// Store values at the time of the login attempt.
165+
String email = mEmailView.getText().toString();
166+
String password = mPasswordView.getText().toString();
167+
168+
boolean cancel = false;
169+
View focusView = null;
170+
171+
// Check for a valid password, if the user entered one.
172+
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
173+
mPasswordView.setError(getString(R.string.error_invalid_password));
174+
focusView = mPasswordView;
175+
cancel = true;
176+
}
177+
178+
// Check for a valid email address.
179+
if (TextUtils.isEmpty(email)) {
180+
mEmailView.setError(getString(R.string.error_field_required));
181+
focusView = mEmailView;
182+
cancel = true;
183+
} else if (!isEmailValid(email)) {
184+
mEmailView.setError(getString(R.string.error_invalid_email));
185+
focusView = mEmailView;
186+
cancel = true;
187+
}
188+
189+
if (cancel) {
190+
// There was an error; don't attempt login and focus the first
191+
// form field with an error.
192+
focusView.requestFocus();
193+
} else {
194+
// Show a progress spinner, and kick off a background task to
195+
// perform the user login attempt.
196+
showProgress(true);
197+
mAuthTask = new UserLoginTask(email, password);
198+
mAuthTask.execute((Void) null);
199+
}
200+
}
201+
202+
private boolean isEmailValid(String email) {
203+
//TODO: Replace this with your own logic
204+
return email.length()==8;
205+
}
206+
207+
private boolean isPasswordValid(String password) {
208+
//TODO: Replace this with your own logic
209+
return password.length() >4;
210+
}
211+
212+
/**
213+
* Shows the progress UI and hides the login form.
214+
*/
215+
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
216+
private void showProgress(final boolean show) {
217+
// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
218+
// for very easy animations. If available, use these APIs to fade-in
219+
// the progress spinner.
220+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
221+
int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
222+
223+
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
224+
mLoginFormView.animate().setDuration(shortAnimTime).alpha(
225+
show ? 0 : 1).setListener(new AnimatorListenerAdapter() {
226+
@Override
227+
public void onAnimationEnd(Animator animation) {
228+
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
229+
}
230+
});
231+
232+
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
233+
mProgressView.animate().setDuration(shortAnimTime).alpha(
234+
show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
235+
@Override
236+
public void onAnimationEnd(Animator animation) {
237+
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
238+
}
239+
});
240+
} else {
241+
// The ViewPropertyAnimator APIs are not available, so simply show
242+
// and hide the relevant UI components.
243+
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
244+
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
245+
}
246+
}
247+
248+
@Override
249+
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
250+
return new CursorLoader(this,
251+
// Retrieve data rows for the device user's 'profile' contact.
252+
Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
253+
ContactsContract.Contacts.Data.CONTENT_DIRECTORY), ProfileQuery.PROJECTION,
254+
255+
// Select only email addresses.
256+
ContactsContract.Contacts.Data.MIMETYPE +
257+
" = ?", new String[]{ContactsContract.CommonDataKinds.Email
258+
.CONTENT_ITEM_TYPE},
259+
260+
// Show primary email addresses first. Note that there won't be
261+
// a primary email address if the user hasn't specified one.
262+
ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
263+
}
264+
265+
@Override
266+
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
267+
List<String> emails = new ArrayList<>();
268+
cursor.moveToFirst();
269+
while (!cursor.isAfterLast()) {
270+
emails.add(cursor.getString(ProfileQuery.ADDRESS));
271+
cursor.moveToNext();
272+
}
273+
274+
addEmailsToAutoComplete(emails);
275+
}
276+
277+
@Override
278+
public void onLoaderReset(Loader<Cursor> cursorLoader) {
279+
280+
}
281+
282+
private void addEmailsToAutoComplete(List<String> emailAddressCollection) {
283+
//Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
284+
ArrayAdapter<String> adapter =
285+
new ArrayAdapter<>(LoginActivity.this,
286+
android.R.layout.simple_dropdown_item_1line, emailAddressCollection);
287+
288+
mEmailView.setAdapter(adapter);
289+
}
290+
291+
292+
private interface ProfileQuery {
293+
String[] PROJECTION = {
294+
ContactsContract.CommonDataKinds.Email.ADDRESS,
295+
ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
296+
};
297+
298+
int ADDRESS = 0;
299+
int IS_PRIMARY = 1;
300+
}
301+
302+
/**
303+
* Represents an asynchronous login/registration task used to authenticate
304+
* the user.
305+
*/
306+
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
307+
308+
private final String mEmail;
309+
private final String mPassword;
310+
311+
UserLoginTask(String email, String password) {
312+
mEmail = email;
313+
mPassword = password;
314+
}
315+
316+
@Override
317+
protected Boolean doInBackground(Void... params) {
318+
// TODO: attempt authentication against a network service.
319+
String login_url = "http://api.zhaoqi.vip/api/v1/urp/login?username="+mEmail+"&password="+mPassword;
320+
try {
321+
String result=httprequest.httpRequest(login_url);
322+
if(result==null)
323+
return false;
324+
Gson gson = new GsonBuilder().create();
325+
LoginResult result1= gson.fromJson(result,LoginResult.class);
326+
if(result1.getStatus()!=200)
327+
return false;
328+
String ss=httprequest.httpRequest("http://api.zhaoqi.vip/api/v1/urp/getCourses");
329+
String a="";
330+
}catch (Exception e){
331+
return false;
332+
}
333+
// TODO: register the new account here.
334+
return true;
335+
}
336+
337+
@Override
338+
protected void onPostExecute(final Boolean success) {
339+
mAuthTask = null;
340+
showProgress(false);
341+
342+
if (success) {
343+
finish();
344+
} else {
345+
mPasswordView.setError(getString(R.string.error_incorrect_password));
346+
mPasswordView.requestFocus();
347+
}
348+
}
349+
350+
@Override
351+
protected void onCancelled() {
352+
mAuthTask = null;
353+
showProgress(false);
354+
}
355+
}
356+
}
357+

0 commit comments

Comments
 (0)