总览
通过建立本次的School Diary应用,您可以更好地体验华为生态系统的组成部分,包括认证服务、云存储和云数据库等Serverless服务。此外您还可以了解到如何使用账号服务集成应用登录功能。老师和学生两种角色的匹配过程是本应用的一大特色。该过程涉及二维码扫描、用户头像保存以及在数据库中匹配细节等环节。
您将建立什么
在本次Codelab中,您将建立一个集成认证服务、统一扫码服务、云数据库和云存储等服务接口的School Diary项目,创建一款端到端的用于为学生和老师处理学校作业任务的应用。老师们可以创建、分发、批改和关闭作业任务。学生们可以查看任务,并上传图片提交作业。
您将学会什么
使用认证服务登录应用。
扫描二维码并匹配老师和学生。
使用云数据库操作让老师们能够创建、分发、批改和关闭作业任务。
使用云存储服务让学生们能够上传和更新作业图片。
Duration: 2:00
开发环境
Duration: 10:00
在接入所需的SDK前,您需要完成以下准备:
在AppGallery Connect上创建一个应用。
创建一个安卓项目。
生成签名证书。
生成签名证书指纹。
配置指纹。
添加应用包名并保存配置文件。
在项目级build.gradle文件中添加AppGallery Connect插件和Maven仓。
在Android Studio中配置签名证书。
详情请参见AppGallery Connect上开通API服务。
您需要首先注册成为一名开发者才能进行以上操作。
Duration: 4:00
在接入相关SDK前,您需要在AppGallery Connect控制台上开启所需权限。操作如下:
1、登录AppGallery Connect 点击“项目设置”中“API管理”页签,开通如下服务的API权限。
认证服务(华为账号认证方式)
云数据库
云存储
统一扫码服务

说明:以上API权限默认已开通。如未开通,请手动开通。
2、在弹出页面设置数据处理位置。

Duration: 4:00
您需要集成云数据库SDK到您的Android Studio项目中。
1、登录AppGallery Connect并点击“我的项目”。
2、选择项目,在应用下拉列表中选择需要集成SDK的应用。
3、选择“项目设置”,进入“常规”页面。在“应用”区域,点击下载“agconnect-services.json”文件。

4、将“agconnect-services.json”文件复制到项目中。

5、在Android Studio中打开项目级“build.gradle”文件。前往allprojects > repositories,然后在buildscript > repositories中配置Maven仓地址。


6、在buildscript > dependencies中配置AppGallery Connect插件地址。
- buildscript {
- dependencies {
- classpath 'com.huawei.agconnect:agcp:
' - }
- }
7、在应用级build.gradle文件中添加AppGallery Connect插件。
apply plugin: 'com.huawei.agconnect'
8、(可选)在Application类的onCreate方法中添加初始化代码。
- if (AGConnectInstance.getInstance() == null) {
- AGConnectInstance.initialize(getApplicationContext());
- }
9、在应用级build.gradle文件中的dependencies代码块中添加所需依赖地址。
- implementation 'com.huawei.agconnect:agconnect-auth:
' - implementation 'com.huawei.hms:hwid:
' - implementation 'com.huawei.hms:scan:
' - implementation "com.huawei.agconnect:agconnect-storage:
" - implementation 'com.huawei.agconnect:agconnect-cloud-database:
'
Duration: 5:00
为您的应用设计如下UI。
老师和学生的登录界面UI。
老师和学生的匹配界面UI。
老师和学生的作业管理界面UI。
学生登录界面UI








老师登录界面UI







Duration: 5:00
认证服务
本次将使用华为账号登录方式。因此,您需要在AppGallery Connect上开启认证服务的华为账号认证方式。否则,登录将失败。
登录AppGallery Connect并点击“我的项目”。
找到并点击项目。
点击“构建”>“认证服务”。如果您首次使用认证服务,请点击“立即开通”。
选择“认证方式”页签,在“操作”列中选择“华为账号”。
云数据库
操作云数据,需要您先开通该服务,然后创建存储区和有着所需字段的云数据库对象。
1、登录AppGallery Connect并点击“我的项目”。
2、点击您的项目。
3、选择“构建”>“云数据库”。如果您首次使用云数据库,请点击“立即开通”。
4、在弹出的页面设置数据处理位置。
5、点击“新增”打开“新增对象类型”页面。

6、设置“对象类型名”为“TaskItem”,点击“下一步”。
7、单击“新增字段”添加如下字段,点击“下一步”。
| 字段 | 类型 | 主键 | 非空 | 加密 | 默认值 |
| TaskID | String | √ | √ | – | – |
| TaskName | String | – | – | – | – |
| TaskDescription | String | – | – | – | – |
| CreatedDate | Date | – | – | – | – |
| DueDate | Date | – | – | – | – |
| CreadtedBy | String | – | – | – | – |
| StudentID | String | – | – | – | – |
| Status | Integer | – | – | – | – |
| SubmittedDate | Date | – | – | – | – |
| group_id | String | – | – | – | – |
| AttachmentUrl | Text | – | – | – | – |
8、单击“下一步”,添加索引。
9、设置角色和对应权限。
10、单击“确定”。返回对象类型列表,查看已创建的对象类型。
11、按照上述操作添加Loginmapping和UserData对象类型。
Loginmapping
| 字段 | 类型 | 主键 | 非空 | 加密 | 默认值 |
| StudentID | String | √ | √ | ||
| StudentName | String | ||||
| StudentEmail | String | ||||
| TeacherID | String | √ | √ | ||
| TeacherName | String | ||||
| TeacherEmail | String | √ | √ | ||
| UserType | Integer | ||||
| MappedDate | Date |
UserData
| 字段 | 类型 | 主键 | 非空 | 加密 | 默认值 |
| UserID | String | ||||
| UserType | String | ||||
| UserName | String | ||||
| TeacherId | String |
12、单击“导出”。
13、选择导出文件格式。此处选择“java格式”,选择java文件类型为“android”,输入包名称,单击“确定”。对象类型文件会以zip形式导出至本地。
14、提取压缩包中的文件至项目的model包里。

15、选择“存储区”页签。
16、单击“新增”,进入创建存储区页面。

云存储
使用云存储服务,您需要首先启用它,并在开始编程前完成下述步骤。
1、云存储开通后,创建一个存储实例并赋名。单击“下一步”。

2、制定安全策略来设置用户是否需要经过验证才能访问存储。
3、完成上述步骤后您就可以使用云存储服务了。
统一扫码服务
统一扫码服务属于HMS Core服务,您无需在AppGallery Connect上进行配置。
Duration: 15:00
完成前提准备后,在您的应用中使用认证服务、云数据库、云存储和统一扫码服务。
1、前往登录界面,输入如下代码实现带有华为账号登录按钮的登录功能。
- binding.loginButton.setOnClickListener(view -> {
- showProgressDialog("Login..." );
- HuaweiIdAuthParamsHelper huaweiIdAuthParamsHelper = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM);
- List<Scope> scopeList = new ArrayList<>();
- scopeList.add(new Scope(HwIDConstant.SCOPE.ACCOUNT_BASEPROFILE));
- huaweiIdAuthParamsHelper.setScopeList(scopeList);
- HuaweiIdAuthParams authParams = huaweiIdAuthParamsHelper.setAccessToken().createParams();
- HuaweiIdAuthService service = HuaweiIdAuthManager.getService(LoginActivity.this, authParams);
- startActivityForResult(service.getSignInIntent(), REQUEST_CODE_SIGN_IN);
- });
2、实现onActivityResult。
- @Override
- protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == REQUEST_CODE_SIGN_IN) {
- Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
- if (authHuaweiIdTask.isSuccessful()) {
- AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
- AGConnectAuthCredential credential = HwIdAuthProvider.credentialWithToken(huaweiAccount.getAccessToken());
- AGConnectAuth.getInstance()
- .signIn(credential)
- .addOnSuccessListener(signInResult -> {
- hideDialog();
- AGConnectUser user = signInResult.getUser();
- validateLogin();
- })
- .addOnFailureListener(e -> {
- hideDialog();
- Log.e(getString(R.string.SIGN_IN_FAILED_TAG), e.getLocalizedMessage());
- });
-
- } else {
- Log.e(getString(R.string.SIGN_IN_FAILED_TAG), getString(R.string.SIGN_IN_FAILED_MSG));
- hideDialog();
- }
- }
- }
3、创建wrapper类用于云数据库存储区初始化和操作对象,例如注入新用户和认证存在用户等。
- public class CloudDBZoneWrapper {
-
- private static final String TAG = "CloudDBZoneWrapper";
- private static final String CLOUD_DB_NAME = "SchoolDB";
- private AGConnectCloudDB mCloudDB;
- private CloudDBZone mCloudDBZone;
- private CloudDBZoneConfig mConfig;
- private UiTaskCallBack mUiTaskCallBack = UiTaskCallBack.DEFAULT;
- private UiStudentCallBack mUiStudentCallBack = UiStudentCallBack.DEFAULT;
-
- public CloudDBZoneWrapper() {
- SchoolDiaryApplication.setRegionRoutePolicy(
- AGConnectInstance.getInstance().getOptions().getRoutePolicy());
- mCloudDB = AGConnectCloudDB.getInstance();
- }
-
- /**
- *设置存储位置
- */
- public void setStorageLocation(Context context) {
- if (mCloudDBZone != null) {
- closeCloudDBZone();
- }
- AGConnectOptionsBuilder builder = new AGConnectOptionsBuilder()
- .setRoutePolicy(SchoolDiaryApplication.getRegionRoutePolicy());
- AGConnectInstance instance = AGConnectInstance.buildInstance(builder.build(context));
- mCloudDB = AGConnectCloudDB.getInstance(instance, AGConnectAuth.getInstance());
- }
-
- /**
- *在Application中初始化AGConnectCloudDB
- * @param context application context
- */
- public static void initAGConnectCloudDB(Context context) {
- AGConnectCloudDB.initialize(context);
- }
-
- /**
- *调用AGConnectCloudDB.createObjectType初始化schema
- */
- public void createObjectType() {
- try {
- mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo());
- } catch (AGConnectCloudDBException e) {
- Log.w(TAG, "createObjectType: " + e.getMessage());
- }
- }
-
- /**
- * 打开存储区
- */
- public void openCloudDBZoneV2(DBZoneListener listener) {
- mConfig = new CloudDBZoneConfig(CLOUD_DB_NAME, CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
- CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
- mConfig.setPersistenceEnabled(true);
- Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true);
- openDBZoneTask.addOnSuccessListener(cloudDBZone -> {
- if (null != listener) {
- listener.getCloudDbZone(cloudDBZone);
- }
- mCloudDBZone = cloudDBZone;
- }).addOnFailureListener(e -> Log.w(TAG, "Open cloudDBZone failed for " + e.getMessage()));
- }
-
- /**
- *调用AGConnectCloudDB.closeCloudDBZone接口
- */
- public void closeCloudDBZone() {
- try {
- mCloudDB.closeCloudDBZone(mCloudDBZone);
- } catch (AGConnectCloudDBException e) {
- Log.w(TAG, "closeCloudDBZone: " + e.getMessage());
- }
- }
-
- /**
- * 添加更新任务列表的回调
- * @param uiTaskCallBack 更新任务列表的回调
- */
- public void addTaskCallBacks(UiTaskCallBack uiTaskCallBack) {
- this.mUiTaskCallBack = uiTaskCallBack;
- }
-
- /**
- * 添加更新用户列表的回调
- */
- public void addStudentCallBacks(UiStudentCallBack uiStudentCallBack) {
- this.mUiStudentCallBack = uiStudentCallBack;
- }
-
-
- /**
- *查询TaskItems
- * @param query 查询条件
- */
- public void queryTasks(CloudDBZoneQuery
query, int tag ) { - if (mCloudDBZone == null) {
- Log.w(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- Task<CloudDBZoneSnapshot<TaskItem>> queryTask = mCloudDBZone.executeQuery(query,
- CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
- queryTask
- .addOnSuccessListener(snapshot -> processQueryResult(snapshot, tag))
- .addOnFailureListener(e -> mUiTaskCallBack.updateUiOnError("DB Query Error, Something went wrong!"));
- }
-
- /**
- *查询UserData及状态
- * @param query 查询条件
- */
- public void queryUserData(CloudDBZoneQuery
query, int tag ) { - if (mCloudDBZone == null) {
- Log.w(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- Task<CloudDBZoneSnapshot<UserData>> queryTask = mCloudDBZone.executeQuery(query,
- CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
- queryTask.addOnSuccessListener(snapshot -> processUsersListResult(snapshot, tag))
- .addOnFailureListener(e -> mUiStudentCallBack.updateStudentUiOnError("DB Query Error, Something went wrong!"));
- }
-
- /**
- *处理UserData和获取查询到的结果
- */
- private void processUsersListResult(CloudDBZoneSnapshot
snapshot, int tag ) { - CloudDBZoneObjectList<UserData> taskItemCursor = snapshot.getSnapshotObjects();
- List<UserData> studentItemList = new ArrayList<>();
- try {
- while (taskItemCursor.hasNext()) {
- UserData studentItem = taskItemCursor.next();
- studentItemList.add(studentItem);
- }
- } catch (AGConnectCloudDBException e) {
- mUiTaskCallBack.updateUiOnError("DB Upsert Error, Something went wrong!");
- } finally {
- snapshot.release();
- }
- mUiStudentCallBack.onStudentAddOrQuery(studentItemList, tag);
- }
-
- /**
- *处理TaskItem和获取查询到的结果
- */
- private void processQueryResult(CloudDBZoneSnapshot
snapshot, int tag ) { - CloudDBZoneObjectList<TaskItem> taskItemCursor = snapshot.getSnapshotObjects();
- List<TaskItem> taskItemList = new ArrayList<>();
- try {
- while (taskItemCursor.hasNext()) {
- TaskItem taskItem = taskItemCursor.next();
- taskItemList.add(taskItem);
- }
- } catch (AGConnectCloudDBException e) {
- mUiTaskCallBack.updateUiOnError("DB Upsert Error, Something went wrong!");
- } finally {
- snapshot.release();
- }
- mUiTaskCallBack.onAddOrQuery(taskItemList, tag);
- }
-
- /**
- *向上插入单个TaskItem
- * @param taskItem 本地添加或修改的TaskItem
- */
- public void upsertTaskItem(TaskItem taskItem, int tag) {
- if (mCloudDBZone == null) {
- Log.w(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- Task<Integer> upsertTask = mCloudDBZone.executeUpsert(taskItem);
- upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
- mUiTaskCallBack.onRefresh(tag);
- }).addOnFailureListener(e -> {
- mUiTaskCallBack.updateUiOnError("DB Upsert Error, Something went wrong!");
- });
- }
-
- /**
- *向上插入大量TaskItem
- * @param taskItem 本地添加或修改的TaskItem
- */
- public void upsertTaskItems(List
taskItem, int tag ) { - if (mCloudDBZone == null) {
- Log.w(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- Task<Integer> upsertTask = mCloudDBZone.executeUpsert(taskItem);
- upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
- mUiTaskCallBack.onRefresh(tag);
- }).addOnFailureListener(e -> {
- mUiTaskCallBack.updateUiOnError("DB Upsert Error, Something went wrong!");
- e.printStackTrace();
- });
- }
-
- /**
- *删除TaskItem
- * @param taskItemList 用户选择的任务
- */
- public void deleteTaskItems(List
taskItemList ) { - if (mCloudDBZone == null) {
- Log.w(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- Task<Integer> deleteTask = mCloudDBZone.executeDelete(taskItemList);
- if (deleteTask.getException() != null) {
- mUiTaskCallBack.updateUiOnError("DB Deletion Error, Something went wrong!");
- return;
- }
-
- }
-
- }
4、该wrapper类包含一些在后续部分可复用的方法。
初始化wrapper,打开存储区,使用CloudDBZoneQuery接口检验用户是否是新用户。
- /**
- * 初始化云数据库和数据库操作用于获取使用ID登录的用户
-
- */
- private void initCloudDB() {
- mCloudDBZoneWrapper = new CloudDBZoneWrapper();
- mHandler = new Handler(Looper.getMainLooper());
- mHandler.post(() -> {
- if (null != AGConnectAuth.getInstance().getCurrentUser()) {
- mCloudDBZoneWrapper.createObjectType();
- mCloudDBZoneWrapper.openCloudDBZoneV2(mCloudDBZone -> {
- this.mCloudDBZone = mCloudDBZone;
- queryUserDetails();
- });
- }
- });
- }
5、存储区初始化成功后,在onInit中执行查询操作验证用户。
- AGConnectUser user = AGConnectAuth.getInstance().getCurrentUser();
- new Handler().post(() -> {
- mCloudDBZoneWrapper
- .queryUserData(CloudDBZoneQuery.where(UserData.class)
- .equalTo("UserID", user.getUid()), 1);
- });
6、在wrapper对象中添加监听器获取查询结果。已注册用户使用任意设备登录应用时,在本地的Shared Preference记录用户类型和匹配状态后,将用户引导至对应的界面。
- mCloudDBZoneWrapper.addStudentCallBacks(new UiStudentCallBack() {
- @Override
- public void onStudentAddOrQuery(List
studentItemList, int tag ) { - hideDialog();
- if (studentItemList.size() > 0) {
- UserData currentUser = studentItemList.get(0);
- int userType = Integer.parseInt(currentUser.getUserType());
- PrefUtil.getInstance(LoginActivity.this).setInt("USER_TYPE", userType);
- PrefUtil.getInstance(LoginActivity.this).setBool("IS_MAPPED", true);
-
- Intent i;
- if (userType == Constants.USER_STUDENT || userType == Constants.USER_TEACHER)
- i = new Intent(LoginActivity.this, HomeActivity.class);
- else
- i = new Intent(LoginActivity.this, UserSelectionActivity.class);
- startActivity(i);
- finish();
- } else {
- Intent i = new Intent(LoginActivity.this, UserSelectionActivity.class);
- startActivity(i);
- finish();
- }
- }
-
- @Override
- public void updateStudentUiOnError(String errorMessage) {
- hideDialog();
- showToast(errorMessage);
- }
- });
7、在页面的onDestroy方法中关闭存储区,否则可能导致错误发生。
若登录用户为新用户,引导至UserSelectionActivty获取用户类型。在选择用户类型后,将用户信息插入到云数据库中(在调用插入接口前需要初始化wrapper)。
- /**
- * 向云数据库中插入用户类型
- */
- public void insertUserType() {
- if (mCloudDBZone == null) {
- Log.e(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- showProgressDialog("Loading...");
- AGConnectUser user = AGConnectAuth.getInstance().getCurrentUser();
- UserData userData = new UserData();
- userData.setUserID(user.getUid());
- userData.setUserName(user.getDisplayName());
- userData.setUserType(String.valueOf(Constants.USER_TEACHER));
-
- Task<Integer> upsertTask = mCloudDBZone.executeUpsert(userData);
- upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
-
- hideDialog();
- Toast.makeText(UserSelectionActivity.this, "TeacherMapActivity_user_insert_success " + cloudDBZoneResult + " records", Toast.LENGTH_SHORT).show();
-
- // 保存匹配状态和当前登录的用户类型。
- PrefUtil.getInstance(UserSelectionActivity.this).setInt("USER_TYPE", Constants.USER_TEACHER);
- PrefUtil.getInstance(UserSelectionActivity.this).setBool("IS_MAPPED", true);
-
- Intent i = new Intent(UserSelectionActivity.this, HomeActivity.class);
- startActivity(i);
- finish();
- });
- upsertTask.addOnFailureListener(e -> {
- hideDialog();
- Log.e(TAG, e.getMessage());
- Toast.makeText(UserSelectionActivity.this, "insert_failed " + e.getLocalizedMessage() + " records", Toast.LENGTH_SHORT).show();
- });
- }
用户信息成功插入后,若用户为学生则引导用户至StudentMapActivity。若用户为老师,直接引导至HomeActivity。
实现老师用户功能
老师的主页面包括两个Fragment。其一是TaskListFragment,其二是StudentListFragment。
TaskListFragment是老师创建的任务列表。
StudentListFragment是老师的学生列表。
1、制作创建作业的按钮UI。基于UI编写代码获取作业名称,作业描述以及提交作业的最晚日期。老师发布作业后,获取老师账户下匹配的学生列表,为每一位学生创建作业任务并将任务信息插入至云数据库。
- /**
- * 收集学生列表,创建任务
- *
-
- *
- 为所有学生创建任务。
- * @param data
- */
- public void upsertTaskItem(Intent data) {
- mCloudDBZoneWrapper.addStudentCallBacks(new UiStudentCallBack() {
- @Override
- public void onStudentAddOrQuery(List
studentItemList, int tag ) { - createAndInsertTaskList(data, studentItemList);
- }
-
- @Override
- public void updateStudentUiOnError(String errorMessage) {
- Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
- }
- });
- new Handler(Looper.getMainLooper()).post(() -> {
- mCloudDBZoneWrapper.queryUserData(CloudDBZoneQuery.where(UserData.class)
- .equalTo("TeacherId", user.getUid())
- .and()
- .equalTo("UserType", String.valueOf(Constants.USER_STUDENT)), 2);
- });
- }
-
- /**
- *根据{@link CreateTaskActivity}获取的信息创建TaskItem的记录
- * 通过 wrapper类插入老师创建的TaskItem
- * 将创建一个具有共同ID的任务组
- * 和为每一个学生分发送一份具有唯一ID的作业任务。
- * @param taskData
- * @param studentsList
- */
- private void createAndInsertTaskList(Intent taskData, List
studentsList ) { - List<TaskItem> taskItemList = new ArrayList();
- Date cDate = new Date();
- String taskGroupId = String.valueOf(UUID.randomUUID()); // unique for each Task
- String date = "";
- for (int ind = 0; ind < studentsList.size(); ind++) {
- TaskItem task = new TaskItem();
- task.setTaskID(String.valueOf(UUID.randomUUID()));//unique for each student
- task.setGroup_id(taskGroupId);
-
- task.setTaskName(taskData.getStringExtra("task_name"));
- task.setTaskDescription(taskData.getStringExtra("task_desc"));
- task.setStatus(Constants.STATUS_NEW);
-
- task.setStudentID(studentsList.get(ind).getUserID());
- task.setCreadtedBy(user.getUid());
-
- date = taskData.getStringExtra("due_date");
- task.setDueDate(UserUtil.localToUTCDate(date));
- task.setCreatedDate(cDate);
- taskItemList.add(task);
- }
- mCloudDBZoneWrapper.upsertTaskItems(taskItemList, 0);
- }
- @Override
- public void onRefresh(int tag) {
- generateTaskListQuery(index);
- }
2、插入数据后,向数据库查询作业列表,展示列表在TaskListFragment。每当进入该Fragment时和作业更新后都应当查询一次作业列表,这样主页就能一直展示最新信息。
- /**
- *创建查询今日TaskItem列表的Query
- * 根据登录用户为老师或学生展示不同的列表
- * 根据参数不同展示当前任务或历史任务
- * @param inputValue
- */
- private void generateTaskListQuery(int inputValue) {
- binding.progressBar.setVisibility(View.VISIBLE);
-
- CloudDBZoneQuery<TaskItem> query;
- Date date = UserUtil.getCurrentDateTimeAsUTC();
- date.setHours(0);
- date.setMinutes(0);
- date.setSeconds(0);
-
- if (inputValue == Constants.TASK_ITEM) {
- query = CloudDBZoneQuery.where(TaskItem.class)
- .greaterThanOrEqualTo("DueDate", date)
- .and().notEqualTo("Status", STATUS_CLOSED);
-
- if (userType == Constants.USER_TEACHER)
- query = query.and().equalTo("CreadtedBy", user.getUid());
-
- if (userType == Constants.USER_STUDENT)
- query = query.and().equalTo("StudentID", user.getUid());
-
- getTaskListFromDB(query);
-
- } else if (inputValue == Constants.TASK_HISTORY_ITEM) {
- query = CloudDBZoneQuery.where(TaskItem.class)
- .lessThanOrEqualTo("DueDate", date)
- .and().equalTo("StudentID", user.getUid());
- getTaskListFromDB(query);
- } else {
- query = CloudDBZoneQuery.where(TaskItem.class);
- getTaskListFromDB(query);
- }
- }
-
- /**
- *调用在wrapper类中定义的方法查询TaskItem
-
- * @param query
- */
- private void getTaskListFromDB(CloudDBZoneQuery
query ) { - new Handler(Looper.getMainLooper()).postDelayed(() -> {
- mCloudDBZoneWrapper.queryTasks(query, 1);
- }, 500);
- }
- @Override
- public void onAddOrQuery(List
taskItemList, int tag ) { - taskItemsList.clear();
- HashMap<String, TaskItem> tempMap = new HashMap<>();
- for (TaskItem taskItem : taskItemList) {
- if (!tempMap.containsKey(taskItem.getGroup_id())) {
- taskItemsList.add(taskItem);
- tempMap.put(taskItem.getGroup_id(), taskItem);
- }
- }
- taskAdapter.updateList(taskItemsList);
- binding.progressBar.setVisibility(View.GONE);
- }
- @Override
- public void updateUiOnError(String errorMessage) {
- Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
- }
3、老师点击任务时,打开TaskSummaryActivity页面。该页面展示作业信息、分配到作业任务的学生列表以及未提交和已提交的作业数量。老师们还可以在该页面上根据状态或需要关闭作业。
- /**
- * 更新当前的任务状态为关闭
- */
- private void closeCurrentTask() {
- if (taskItems.size() > 0) {
- List<TaskItem> closeTaskItems = new ArrayList<>();
- for (int i = 0; i < taskItems.size(); i++) {
- TaskItem taskItem = taskItems.get(i).getTaskItem();
- taskItem.setStatus(Constants.STATUS_CLOSED);
- closeTaskItems.add(taskItem);
- }
- new Handler(Looper.getMainLooper()).post(() -> {
- mCloudDBZoneWrapper.upsertTaskItems(closeTaskItems, 3);
- });
- }
- }
-
- /**
- *从数据库中获取任务列表
- * @param groupId
- */
- private void getSubmittedTaskList(String groupId) {
- new Handler(Looper.getMainLooper()).post(() -> {
- mCloudDBZoneWrapper.queryTasks(CloudDBZoneQuery.where(TaskItem.class).equalTo("group_id", groupId), 1);
- });
- }
-
- @Override
- public void onAddOrQuery(List
taskItemList, int tag ) { - taskItems.clear();
- for (int ind = 0; ind < taskItemList.size(); ind++) {
- UserAndTask userAndTask = new UserAndTask();
- userAndTask.setTaskItem(taskItemList.get(ind));
- taskItems.add(userAndTask);
- }
- getStudentList();
- }
-
- /**
- *从数据库获取学生列表
- */
- private void getStudentList() {
- new Handler().post(() -> {
- mCloudDBZoneWrapper.queryUserData(
- CloudDBZoneQuery.where(UserData.class)
- .equalTo("UserType", String.valueOf(Constants.USER_STUDENT))
- .and()
- .equalTo("TeacherId", user.getUid()),
- 2);
- });
- }
- @Override
- public void onStudentAddOrQuery(List
studentItemList, int tag ) { - int pendingCount = 0, submittedCount = 0, evaluatedCount = 0;
- for (int ind = 0; ind < taskItems.size(); ind++) {
- //获取计数
- int tStatus = taskItems.get(ind).getTaskItem().getStatus();
- pendingCount += (tStatus == Constants.STATUS_NEW) ? 1 : 0;
- submittedCount += (tStatus == Constants.STATUS_SUBMITTED) ? 1 : 0;
- evaluatedCount += (tStatus == Constants.STATUS_EVALUATED) ? 1 : 0;
- //匹配任务和学生
- for (int jnd = 0; jnd < studentItemList.size(); jnd++) {
- if (taskItems.get(ind).getTaskItem().getStudentID().equals(studentItemList.get(jnd).getUserID())) {
- taskItems.get(ind).setUserData(studentItemList.get(jnd));
- }
- }
- }
- taskSumListAdapter.updateList(taskItems);
- displayTaskDetails(taskItems.get(0).getTaskItem(), pendingCount, submittedCount, evaluatedCount);
- hideDialog();
- }
4、学生上传的作业可以被老师批改。老师只需点击某位学生的作业即可。点击作业后打开TaskDetailActivtiy。该页面处理老师的作业批改和学生的作业提交。添加如下代码实现作业批改。
- binding.btnValidateTask.setOnClickListener(v -> {
- if (validatePreValidation(taskItem)) {
- updateValidateStatus(taskItem);
- }
- });
- /**
- * 验证作业任务是否可以被批改
- */
- private boolean validatePreValidation(TaskItem taskParam) {
- if (taskParam.getStatus() == Constants.STATUS_NEW) {
- showToast("Not submitted, Cannot evaluate");
- return false;
- } else if (taskParam.getStatus() == Constants.STATUS_EVALUATED) {
- showToast("Task already evaluated");
- return false;
- } else if (taskParam.getStatus() == Constants.STATUS_CLOSED) {
- showToast("Task Closed, Cannot evaluate");
- return false;
- } else if (taskParam.getAttachmentUrl() == null || taskParam.getAttachmentUrl().get().isEmpty()) {
- showToast("No Attachment, Cannot evaluate");
- return false;
- } else {
- return true;
- }
- }
- /**
- *当老师批改作业时更新作业状态
- *更新老师批时的作业状态
- */
- private void updateValidateStatus(TaskItem taskParam) {
- showProgressDialog("Updating Task status..");
- taskParam.setStatus(Constants.STATUS_EVALUATED);
- new Handler(Looper.getMainLooper()).post(() -> {
- mCloudDBZoneWrapper.upsertTaskItem(taskParam, VALIDATE);
- });
- }
- @Override
- public void onRefresh(int tag) {
- hideDialog();
- if (tag == VALIDATE || tag == SUBMIT) {
- String msg = tag == VALIDATE ? "Task Validated." : "Task Submitted.";
- showAlertDialog(msg, () -> {
- HomeActivity.NEED_UPDATE = true;
- finish();
- });
- } else if (tag == ATTACHMENT) {
- showToast("File uploaded Successfully");
- }
- }
5、StudentsListFragment仅展示HomeActivity第二个页签的学生列表。执行数据库查询操作获取学生列表。
- /**
- * 执行查询操作获取学生列表
- * @param inputValue
- * @param teacherId
- */
- private void getStudentList(int inputValue, String teacherId) {
- binding.progressBar.setVisibility(View.VISIBLE);
- CloudDBZoneQuery<UserData> query;
- if (inputValue == Constants.STUDENT_ITEM) {
- query = CloudDBZoneQuery.where(UserData.class)
- .equalTo("TeacherId", teacherId)
- .and()
- .equalTo("UserType", String.valueOf(Constants.USER_STUDENT));
- getListData(query);
- } else {
- query = CloudDBZoneQuery.where(UserData.class);
- getListData(query);
- }
- }
-
- /**
- *调用wrapper类方法获取UserData
- * @param query
- */
- private void getListData(CloudDBZoneQuery
query ) { - new Handler().postDelayed(() -> {
- mCloudDBZoneWrapper.queryUserData(query, 1);
- }, 300);
- }
-
-
- /**
- 数据库监听器方法
- *OnResult方法实现检索学生列表
- * @param studentItemList
- * @param tag
- */
- @Override
- public void onStudentAddOrQuery(List
studentItemList, int tag ) { - studentAdapter.updateList(studentItemList);
- binding.progressBar.setVisibility(View.GONE);
- }
-
- /**
- *数据库监听器方法
- *OnError方法实现检索学生列表
- * @param errorMessage
- */
- @Override
- public void updateStudentUiOnError(String errorMessage) {
- Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show();
- }
6、若老师想查看学生历史作业任务,可以点击列表中的某位学生,然后打开StudentDetailActivity页面。在该页面中执行数据库查询操作获取列表。
- /**
- *添加UserData数据库操作监听器
- *通过wrapper类获取学生列表
- */
- public void queryUserDetails() {
- mCloudDBZoneWrapper.addStudentCallBacks(new UiStudentCallBack() {
- @Override
- public void onStudentAddOrQuery(List
studentItemList, int tag ) { - hideDialog();
- if (studentItemList.size() > 0) {
- UserData currentUser = studentItemList.get(0);
- binding.txtStudentName.setText(currentUser.getUserName());
- binding.txtStudentDetail.setText("My Student");
- getTaskList(currentUser.getUserID());
- }
- }
-
- @Override
- public void updateStudentUiOnError(String errorMessage) {
- hideDialog();
- showToast(errorMessage);
- }
- });
- new Handler().post(() -> {
- mCloudDBZoneWrapper.queryUserData(CloudDBZoneQuery.where(UserData.class).equalTo("UserID", studentId), 1);
- });
- }
-
- /**
- *创建用于获取特定学生数据的Query
- * @param studentId
- */
- private void getTaskList(String studentId) {
- CloudDBZoneQuery<TaskItem> query;
- query = CloudDBZoneQuery.where(TaskItem.class).equalTo("StudentID", studentId);
- getListData(query);
- }
-
- /**
- *
- * @param query
- */
- private void getListData(CloudDBZoneQuery
query ) { - new Handler().post(() -> {
- mCloudDBZoneWrapper.queryTasks(query, 1);
- });
- }
-
- /**
- *数据库监听器方法
- *OnResult方法实现检索TaskItem列表
- * @param taskItemList
- * @param tag
- */
- @Override
- public void onAddOrQuery(List
taskItemList, int tag ) { - hideDialog();
- taskListAdapter.updateList(taskItemList);
- }
-
- /**
- *数据库监听器方法
- *onError实现检索TaskItem列表
- * @param errorMessage
- */
- @Override
- public void updateUiOnError(String errorMessage) {
- hideDialog();
- showToast(errorMessage);
- }
7、老师信息和二维码将展示在TeachersProfileActivity页面。添加下述代码生成老师的二维码。
- /**
- *初始化View,生成和展示带有老师信息的二维码
- *学生通过扫描该二维码可以匹配该老师
- * @param savedInstanceState
- */
- @Override
- protected void onPostCreate(@Nullable Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
- AGConnectUser user = AGConnectAuth.getInstance().getCurrentUser();
- String content = "{\"TeacherID\":\"" + user.getUid() + "\"," +
- "\"TeacherName\":\"" + user.getDisplayName() + "\"," +
- "\"EmailID\":\"" + user.getEmail() + "\"}";
-
- binding.txtTeacherName.setText(user.getDisplayName());
- binding.txtTeacherId.setText((user.getEmail() == null) ? "" : user.getEmail());
-
- int type = HmsScan.QRCODE_SCAN_TYPE;
- int width = 400;
- int height = 400;
-
- HmsBuildBitmapOption options = new HmsBuildBitmapOption.Creator().setBitmapMargin(3).create();
- try {
- //若HmsBuildBitmapOption对象未构建,将options设置为null。
- qrBitmap = ScanUtil.buildBitmap(content, type, width, height, options);
- ((ImageView) findViewById(R.id.img_teacher_qr)).setImageBitmap(qrBitmap);
- } catch (WriterException e) {
- Log.w("buildBitmap", e);
- }
- }
实现学生用户功能
在StudentMapActivty页面,添加二维码扫描功能。通过统一扫码服务,学生可以扫码匹配老师。
初始化统一扫码服务扫描页面,实现onActivityResult方法。老师的二维码包含一串由统一扫码服务根据老师登录信息生成的JSON数据。
使用Intent中的结果数据在该Activity中执行下述数据库操作。
1、创建Loginmapping云数据库对象。
2、创建UserData云数据对象。
- /**
- *开启相机二维码扫描
- */
- private void initScanQR() {
- HmsScanAnalyzerOptions options = new HmsScanAnalyzerOptions.Creator()
- .setHmsScanTypes(HmsScan.QRCODE_SCAN_TYPE, HmsScan.DATAMATRIX_SCAN_TYPE)
- .create();
- ScanUtil.startScan(StudentMapActivity.this, REQUEST_CODE, options);
- }
-
- /**
- *二维码扫描后
- *传入老师二维码中的JSON对象
- * @param requestCode
- * @param resultCode
- * @param data
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (resultCode != RESULT_OK || data == null) {
- return;
- }
- if (requestCode == REQUEST_CODE) {
- //传入扫描的图片并返回结果。
- HmsScan obj = data.getParcelableExtra(ScanUtil.RESULT);
- if (obj != null && !TextUtils.isEmpty(((HmsScan) obj).getOriginalValue())) {
- try {
- /*二维码中的老师信息以JSON格式返回。*/
- JSONObject jsonObject = new JSONObject(obj.getOriginalValue());
- initCloudDB(jsonObject);
-
- } catch (JSONException e) {
- Log.e(TAG, e.getMessage());
- }
- } else {
- Log.e("Error", "Scanned result (null) not available");
- }
- } else {
- Log.e("Error", "Scanned result not available");
- }
-
- }
-
- /**
- *初始化wrapper类。初始化完成后,调用数据库插入操作方法。
- * @param jsonObject
- */
- private void initCloudDB(JSONObject jsonObject) {
- mCloudDBZoneWrapper = new CloudDBZoneWrapper();
- mHandler = new Handler(Looper.getMainLooper());
- mHandler.post(() -> {
- if (null != AGConnectAuth.getInstance().getCurrentUser()) {
- mCloudDBZoneWrapper.createObjectType();
- mCloudDBZoneWrapper.openCloudDBZoneV2(mCloudDBZone1 -> {
- this.mCloudDBZone = mCloudDBZone1;
- try {
- upsertTeacherDetails(jsonObject);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- });
- }
- });
- }
- /**
- *向云数据库中的LoginMapping插入老师和学生的匹配记录
-
- * @param jsonObject
- * @throws JSONException
- */
- public void upsertTeacherDetails(JSONObject jsonObject) throws JSONException {
- if (mCloudDBZone == null) {
- Log.e(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
- showProgressDialog("Loading...");
-
- AGConnectUser user = AGConnectAuth.getInstance().getCurrentUser();
- String teacherId = jsonObject.getString("TeacherID");
-
- Loginmapping loginmapping = new Loginmapping();
- loginmapping.setStudentID(user.getUid());
- loginmapping.setTeacherID(teacherId);
- loginmapping.setStudentName(user.getDisplayName());
- loginmapping.setStudentEmail(user.getEmail());
- loginmapping.setTeacherEmail(jsonObject.getString("EmailID"));
- loginmapping.setTeacherName(jsonObject.getString("TeacherName"));
- //loginmapping.setUserType(1);
- Date date = new Date();
- loginmapping.setMappedDate(date);
-
- Task<Integer> upsertTask = mCloudDBZone.executeUpsert(loginmapping);
- upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
- insertUserType(teacherId);
- }).addOnFailureListener(e -> {
- hideDialog();
- Log.e("TAG", "insert_failed " + e.getLocalizedMessage() + " records");
- });
- }
- /**
- *插入匹配后的学生记录
- * @param teacherId
- */
- public void insertUserType(String teacherId) {
- if (mCloudDBZone == null) {
- Log.e(TAG, "CloudDBZone is null, try re-open it");
- return;
- }
-
- AGConnectUser user = AGConnectAuth.getInstance().getCurrentUser();
- UserData userData = new UserData();
- userData.setUserID(user.getUid());
- userData.setUserName(user.getDisplayName());
- userData.setUserType(String.valueOf(Constants.USER_STUDENT));
- userData.setTeacherId(teacherId);
-
- Task<Integer> upsertTask = mCloudDBZone.executeUpsert(userData);
- upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
- hideDialog();
- Toast.makeText(StudentMapActivity.this, "Student Registered and Mapped.", Toast.LENGTH_SHORT).show();
- if (!initFrom.equals("StudentProfileActivity")) {
- PrefUtil.getInstance(this).setInt("USER_TYPE", Constants.USER_STUDENT);
- PrefUtil.getInstance(this).setBool("IS_MAPPED", true);
- startActivity(new Intent(StudentMapActivity.this, HomeActivity.class));
- }
- finish();
- });
-
- upsertTask.addOnFailureListener(e -> {
- hideDialog();
- Log.e(TAG, "insert_failed " + e.getLocalizedMessage() + " records");
- });
- }
3、匹配成功后,引导学生至HomeActivtiy。该页面包括两部分。复用TaskListFragment作为“Current Task”和“Task History”页签
Current Task页签列举需要完成的作业。
Task History列举所有历史作业。
- /**
- *创建获取今日TaskItem列表的Query
- * 基于登录用户,展示不同列表
- *根据参数不同展示当前TaskItem列表或历史任务
- * @param inputValue
- */
- private void generateTaskListQuery(int inputValue) {
- binding.progressBar.setVisibility(View.VISIBLE);
-
- CloudDBZoneQuery<TaskItem> query;
- Date date = UserUtil.getCurrentDateTimeAsUTC();
- date.setHours(0);
- date.setMinutes(0);
- date.setSeconds(0);
-
- if (inputValue == Constants.TASK_ITEM) {
- query = CloudDBZoneQuery.where(TaskItem.class)
- .greaterThanOrEqualTo("DueDate", date)
- .and().notEqualTo("Status", STATUS_CLOSED);
-
- if (userType == Constants.USER_TEACHER)
- query = query.and().equalTo("CreadtedBy", user.getUid());
-
- if (userType == Constants.USER_STUDENT)
- query = query.and().equalTo("StudentID", user.getUid());
-
- getTaskListFromDB(query);
-
- } else if (inputValue == Constants.TASK_HISTORY_ITEM) {
- query = CloudDBZoneQuery.where(TaskItem.class)
- .lessThanOrEqualTo("DueDate", date)
- .and().equalTo("StudentID", user.getUid());
- getTaskListFromDB(query);
- } else {
- query = CloudDBZoneQuery.where(TaskItem.class);
- getTaskListFromDB(query);
- }
- }
- private void getTaskListFromDB(CloudDBZoneQuery
query ) { - new Handler(Looper.getMainLooper()).postDelayed(() -> {
- mCloudDBZoneWrapper.queryTasks(query, 1);
- }, 500);
- }
- @Override
- public void onAddOrQuery(List
taskItemList, int tag ) { - taskItemsList.clear();
- HashMap<String, TaskItem> tempMap = new HashMap<>();
- for (TaskItem taskItem : taskItemList) {
- if (!tempMap.containsKey(taskItem.getGroup_id())) {
- taskItemsList.add(taskItem);
- tempMap.put(taskItem.getGroup_id(), taskItem);
- }
- }
- taskAdapter.updateList(taskItemsList);
- binding.progressBar.setVisibility(View.GONE);
- }
4、学生点击HomeActivity上对应的作业任务打开TaskDetailActivity页面后,上传作业图片。实现下述步骤。
1)从相册中挑选照片,上传照片至云存储,并获取上传照片的URL地址。
- binding.btnUpload.setOnClickListener(view -> uploadFile(view));
- /**
- *检查初始化后的云存储
- *调用图片挑选方法
- */
- public void uploadFile(View view) {
- if (mAGCStorageManagement == null) {
- initAGCStorageManagement();
- }
- pickImageFromGallery();
- }
-
- /**
- *初始化从设备相册挑选相册功能
- */
- private void pickImageFromGallery() {
- Uri filePath = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath());
- //Uri filePath = Uri.parse("/storage/");
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setDataAndType(filePath, "image/*");
- startActivityForResult(intent, PICKFILE_REQUEST_CODE);
- }
- /**
- * 获取图片的挑选结果并转成bitmap
- *将结果传入云存储的上传方法中
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == PICKFILE_REQUEST_CODE && resultCode == RESULT_OK && null != data) {
- imageUri = data.getData();
- ImageView imageView = new ImageView(TaskDetailActivity.this);
- imageView.setImageURI(imageUri);
- imageView.invalidate();
- BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
- uploadImageToCloud(drawable.getBitmap());
- }
- }
-
- /**
- *为图片名称生成随机字串
- *开启图片上传异步方法
- */
- private void uploadImageToCloud(Bitmap bitmap) {
- showProgressDialog("Uploading... ");
- final String randomKey = UUID.randomUUID().toString();
- FileFromBitmap fileFromBitmap = new FileFromBitmap(bitmap, randomKey, TaskDetailActivity.this);
- fileFromBitmap.execute();
- }
- /**
- *图片上传AsyncTask类
- *doInBackground:通过相册路径获取文件
- *onPostExecute:上传至云存储
- *获取上传的文件URL用于展示或查看
- */
- class FileFromBitmap extends AsyncTask<Void, Integer, File> {
- Context context;
- Bitmap bitmap;
- String fileName;
-
- public FileFromBitmap(Bitmap bitmap, String fileName, Context context) {
- this.bitmap = bitmap;
- this.context = context;
- this.fileName = fileName;
- }
-
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- }
-
- @Override
- protected File doInBackground(Void... voids) {
- File fileBackGround = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), fileName);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
- byte[] bitmapdata = bos.toByteArray();
- FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(fileBackGround);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- try {
- fos.write(bitmapdata);
- fos.flush();
- fos.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return fileBackGround;
- }
-
- @Override
- protected void onPostExecute(File file) {
- if (!file.exists()) {
- return;
- }
- StorageReference storageReference = mAGCStorageManagement.getStorageReference(file.getPath());
- //成功则上传文件和获取URL
- UploadTask uploadTask = storageReference.putFile(file);
- Task<Uri> urlTask = uploadTask.continueWithTask(task -> {
- if (!task.isSuccessful()) {
- throw task.getException();
- }
- return storageReference.getDownloadUrl();
- });
- //上传完成后发送URL
- urlTask.addOnCompleteListener(task -> {
- if (task.isSuccessful()) {
- Uri downloadUri = task.getResult();
- System.out.println("Upload " + downloadUri);
- hideDialog();
- if (downloadUri != null) {
- String photoStringLink = downloadUri.toString(); //此处存储下载地址。
- addImageInRecyclerView(photoStringLink);
- }
- }
- });
- uploadTask.addOnSuccessListener(uploadResult -> hideDialog())
- .addOnFailureListener(e -> hideDialog());
- }
- }
2)串联所有上传的图片URL并更新相应任务的URL。
- /**
- *当学生上传附件时更新附件URL
- *需使用wrapper类的upsertTaskItem方法
- */
- private void updateAttachURL(String uploadUrL) {
- showProgressDialog("Updating your attachments..");
-
- String str = taskItem.getAttachmentUrl() == null ? "" : taskItem.getAttachmentUrl().get();
- str += (str.isEmpty()) ? uploadUrL : ", " + uploadUrL;
- taskItem.setAttachmentUrl(new Text(str)); // 此处为附件URL字符串,多个地址用逗号隔开.
-
- new Handler(Looper.getMainLooper()).postDelayed(() -> {
- mCloudDBZoneWrapper.upsertTaskItem(taskItem, ATTACHMENT);
- }, 500);
- }
- @Override
- public void onRefresh(int tag) {
- hideDialog();
- if (tag == VALIDATE || tag == SUBMIT) {
- String msg = tag == VALIDATE ? "Task Validated." : "Task Submitted.";
- showAlertDialog(msg, () -> {
- HomeActivity.NEED_UPDATE = true;
- finish();
- });
- } else if (tag == ATTACHMENT) {
- showToast("File uploaded Successfully");
- }
- }
3)任务中的URL更新后,接下来提交任务。提交完成后,任务状态变为“SUBMITTED”。
- binding.btnSubmitTask.setOnClickListener(v -> {
- if (submitPreValidation(taskItem)) {
- updateSubmissionStatus(taskItem);
- }
- });
- /**
- *验证任务数据是否能够被学生提交
- */
- private boolean submitPreValidation(TaskItem taskParam) {
- if (taskParam.getStatus() == Constants.STATUS_SUBMITTED) {
- showToast("Task Already submitted");
- return false;
- } else if (taskParam.getStatus() == Constants.STATUS_EVALUATED) {
- showToast("Task evaluated, Cannot Submit");
- return false;
- } else if (taskParam.getStatus() == Constants.STATUS_CLOSED) {
- showToast("Task Closed, Cannot Submit");
- return false;
- } else if (taskParam.getAttachmentUrl() == null || taskParam.getAttachmentUrl().get().isEmpty()) {
- showToast("No Attachment, Cannot submit");
- return false;
- } else {
- return true;
- }
- }
-
- /**
- *学生提交作业时更新任务状态
- *需使用wrapper类的upsertTaskItem方法
- */
- private void updateSubmissionStatus(TaskItem task_Item) {
- showProgressDialog("Updating your attachments..");
- task_Item.setStatus(Constants.STATUS_SUBMITTED);
- new Handler(Looper.getMainLooper()).post(() -> {
- mCloudDBZoneWrapper.upsertTaskItem(task_Item, SUBMIT);
- Toast.makeText(this, "Url Updated successfully", Toast.LENGTH_SHORT).show();
- });
- }
-
- @Override
- public void onRefresh(int tag) {
- hideDialog();
- if (tag == VALIDATE || tag == SUBMIT) {
- String msg = tag == VALIDATE ? "Task Validated." : "Task Submitted.";
- showAlertDialog(msg, () -> {
- HomeActivity.NEED_UPDATE = true;
- finish();
- });
- } else if (tag == ATTACHMENT) {
- showToast("File uploaded Successfully");
- }
- }
1、启用Androd Studio, 单击运行按钮在手机或模拟器上运行应用。点击登录按钮登录应用。


2、成功登录后,选择用户类型。

3、如果用户是学生,则需要扫码匹配老师。

4、老师的二维码在其个人主页下展示。

5、匹配成功后显示主页。
学生主页

老师主页

6、老师们点击主页“+”按钮创建任务。

7、学生和老师的主页都可以展示创建完成的任务。

8、学生可以在主页点击任务并更新任务状态。


9、老师可以查看任务状态和学生的历史任务。


祝贺您,您已成功构建一款School Diary应用并学会了:
在AppGallery Connect上配置云数据库和云存储。
使用Android Studio集成多个HMS Core服务并构建一款School Diary应用。
参考如下文档获取更多信息:
点击此处下载源码。
声明:本codelab实现多个HMS Core服务在单个项目中的集成,供您参考。您需要验证确保相关开源代码的安全合法合规。
欲了解更多更全技术文章,欢迎访问https://developer.huawei.com/consumer/cn/forum/?ha_source=zzh