出席トラッカーAndroidのアプリでルームデータベースとHuawei Analyticsキットを使用して出席タイミングを入力-パート5



導入
本論文では,ルームデータベースによるユーザの時間と外出時間の入力方法について学び,イベント追跡のための解析キットを統合できる.
部屋はORM(オブジェクト関係マッピング)ライブラリです.つまり、データベースオブジェクトはJavaオブジェクトにマップされます.SQLiteの完全なパワーを活用しながら、流暢なデータベースアクセスを許可するようにSQLiteの上に抽象化層を提供します.部屋はSQLiteデータベースを作成し、作成、読み取り、更新、削除のような操作を行うことができます.
したがって、私は他のHuaweiキットを統合する今後の記事では、この出席トラッカーアプリに関する記事のシリーズを提供します.
このアプリケーションに新しい場合は、私の前の記事に従ってください
Beginner: Integration of Huawei Account Kit of Obtaining Icon Resources feature in Attendance Tracker Android app (Kotlin) - Part 1
Beginner: Find Log in via SMS and Forgot password? Features using Huawei Account Kit, and Ads Kit in Attendance Tracker Android app (Kotlin) – Part 2
Beginner: Find the CRUD operations in Room Database in Attendance Tracker Android app (Kotlin) – Part 3
Beginner: Integration of Huawei Crash Service in Attendance Tracker Android app (Kotlin) – Part 4
解析キット
Huawei Analyticsキットは、ユーザーの行動を理解し、ユーザー、製品やコンテンツに深い洞察力を得るために分析モデルを提供しています.それはあなたのユーザーの行動のイベントやユーザーの属性を介して別のプラットフォーム上のユーザーの行動についての洞察力を得るためにアプリを介して報告を得るのに役立ちます.
接続ギャラリー
AppGallery接続ダッシュボードを使用して解析をして下さい.
プロジェクトを選択します.
プロジェクトの概要は、新しいユーザーの数、ユーザーアクティビティ、ユーザーの取得、ユーザーの再訪問、ユーザーの再利用、アクティブなユーザーの保持、ユーザーの特性と人気のページなどの現在のプロジェクトのコアインジケータが表示されますユーザーの簡単な概要を提供し、どのようにあなたのアプリケーションを使用している.



要件
  • オペレーティングシステム(MacOS、Linux、Windows).
  • はHMS 4.0.0.300以降でHuawei電話を持たなければなりません.
  • は、Android Studio、JDK 1.8、SDKプラットフォーム26とGradle 4.6を搭載したラップトップまたはデスクトップを持っていなければなりません.
  • 最小APIレベル24が必要です.
  • EMUI 9.0.0以降のバージョンデバイスが必要です.
  • HMS依存関係を統合する方法
  • はHuawei開発者として登録され、Huawei開発者ウェブサイトで完全なアイデンティティ検証を行う.
  • Android Studioでプロジェクトを作成します.
  • SHA - 256証明書指紋を生成します.
  • SHA - 256証明書指紋を生成する
  • .Android Project Class Gradleの右上隅に、「プロジェクト名」「タスク」「Android」を選択し、「次へ」をクリックします.
  • Huawei ID
    注意:プロジェクト名は、ユーザーが作成した名前によって異なります.

  • Creating an Android Studio Project .
  • AppConnectサービスをダウンロードします.JSONファイルのアプリ情報、コピーと貼り付けアプリのディレクトリの下にAndroidのプロジェクトでは、次のように.
  • SHA - 256証明書指紋を入力し、保存ボタンをクリックします.
  • Create an App in AppGallery Connect
  • 管理タブをクリックし、Huawei Analyticsを有効にします.
  • ビルド中のMaven URLを追加します.buildScript、依存関係、およびすべてのプロジェクトのリポジトリの下にあるGradleプロジェクト.maven { url 'http://developer.huawei.com/repo/' } classpath 'com.huawei.agconnect:agcp:1.6.0.300'
  • ビルドでプラグインと依存関係を追加します.gradle ( module )ファイル.apply plugin: id 'com.huawei.agconnect' apply plugin: id 'kotlin-kapt' // Huawei AGC implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300' // Room Database implementation "androidx.room:room-runtime:2.4.2" kapt "androidx.room:room-compiler:2.4.2" implementation "androidx.room:room-ktx:2.4.2" androidTestImplementation "androidx.room:room-testing:2.4.2" // Lifecycle components implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1" // Recyclerview implementation 'androidx.recyclerview:recyclerview:1.2.1' // Huawei Analytics implementation 'com.huawei.hms:hianalytics:6.4.0.300'
  • 今Gradleを同期します.
  • AndroidManifestに必要なアクセス許可を追加します.XMLファイル.<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
  • 発展に移ろう
    私は、私たちがコーディングを始めさせようとしていない空の活動でAndroid Studioでプロジェクトを作成しました.
    Huawei Analyticsを初期化し、それを有効にします.
    解析の初期化
    var minstat : HiAnalyticsInstance ?=NULL
    //解析関数を初期化する
    initana ()
    プライベート楽しいinitana () {
    //解析キットを有効にする
    HiAnalyticstols.enable ()
    //解析のインスタンスを生成する
    ミンスタンス= HiAnalytics.getinstance (この関数)
    //コレクション機能を有効にする
    ミンスタンス?解析される

    punchrecordを作成します.各クラスのテーブルを作成するには、@ entityに注釈付きのクラスを追加します.@Entity(tableName = "punchrecords")
    data class PunchRecord(
    @PrimaryKey(autoGenerate = true)
    val id: Long,
    val empid: String,
    val intime: String,
    val outtime: String
    )
    punchRecorddaoを作成します.KTインターフェイスクラスで、データベースにアクセスするメソッドを定義するために注釈を付けます.
    `
    インターフェース
    クエリを選択します
    楽しいpunchgetall () : livedata >
    @Insert(onConflict = OnConflictStrategy.ABORT)
    suspend fun insert(item: PunchRecord)
    
    @Query("SELECT * FROM punchrecords WHERE punchrecords.id == :id")
    fun get(id: Long): LiveData<PunchRecord>
    
    @Update
    suspend fun update(vararg items: PunchRecord)
    
    @Delete
    suspend fun delete(vararg items: PunchRecord)
    

    データベースを作成します.データベースに含まれるエンティティ、およびそれらにアクセスするDAOSを一覧表示するには、@データベースで注釈を付けられたRoomDatabaseを拡張するKT抽象クラス.
    データベースを使用します.
    抽象クラス
    abstract fun punchrecordDao(): PunchRecordDao
    
    companion object {
        @Volatile
        private var INSTANCE: RoomDatabase? = null
    
        fun getDatabase(context: Context): PunchAppRoomDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance as PunchAppRoomDatabase
            }
            synchronized(this) {
                val instance = Room.databaseBuilder(context.applicationContext,PunchAppRoomDatabase::class.java,
                    "datarecords_database").fallbackToDestructiveMigration()
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
    

    punchRepositoryを作成します.KTクラスは関数を見つける.
    `クラスPunchRepository ( private val punchdao : punchrecorddao ) { }
    val myallItems: LiveData<List<PunchRecord>> = punchDao.punchgetall()
    
    fun getrepo(id: Long):LiveData<PunchRecord> {
        return punchDao.get(id)
    }
    suspend fun updatepunch(item: PunchRecord) {
        punchDao.update(item)
    }
    suspend fun insertpunch(item: PunchRecord) {
        punchDao.insert(item)
    }
    suspend fun deletepunch(item: PunchRecord) {
        punchDao.delete(item)
    }
    

    punchviewmodelを作成します.AndroidViewModelを拡張し、punchRepository関数を提供するKTクラスです.
    `クラスPunchViewModel ( Application : Application ): AndroidViewModel ( Application ) { { }
    private val repository: PunchRepository
    val allPunchItems: LiveData<List<PunchRecord>>
    
    init {
        Log.d(ContentValues.TAG, "Inside ViewModel init")
        val dao = PunchAppRoomDatabase.getDatabase(application).punchrecordDao()
        repository = PunchRepository(dao)
        allPunchItems = repository.myallItems
    }
    
    fun insert(item: PunchRecord) = viewModelScope.launch {
        repository.insertpunch(item)
    }
    
    fun update(item: PunchRecord) = viewModelScope.launch {
        repository.updatepunch(item)
    }
    
    fun delete(item: PunchRecord) = viewModelScope.launch {
        repository.deletepunch(item)
    }
    
    fun get(id: Long) = repository.getrepo(id)
    

    雇用主活動で.KT活動は、ボタンクリックのためにビジネスロジックを見つけます.
    `クラス管理関数: appcompatactivit () {
    private var buttonAddPunch: Button? = null
    private lateinit var myViewModel: PunchViewModel
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_emp_login)
    
        val recyclerView = recyclerview_list
        val adapter = PunchAdapter(this)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)
    
        buttonAddPunch = findViewById(R.id.btn_punch)
        buttonAddPunch!!.setOnClickListener(View.OnClickListener {
            val intent = Intent(this, TimeActivity::class.java)
            startActivity(intent)
        })
    
        myViewModel = ViewModelProvider(this)[PunchViewModel::class.java]
        myViewModel.allPunchItems.observe(this, Observer { items ->
            items?.let { adapter.setItems(it) }
        })
    
    }
    

    punchAdapterを作成します.リストを保持するKTアダプタークラス.
    ` class punchAdapter内部のコンストラクタ( context : context ): RefererView.アダプタ()
    private val inflater: LayoutInflater = LayoutInflater.from(context)
    private var itemsList = emptyList<PunchRecord>().toMutableList()
    private val onClickListener: View.OnClickListener
    
    init {
        onClickListener = View.OnClickListener { v ->
            val item = v.tag as PunchRecord
            Log.d(TAG, "Setting onClickListener for item ${item.id}")
            val intent = Intent(v.context, TimeActivity::class.java).apply {
                putExtra(DATA_RECORD_ID, item.id)
            }
            v.context.startActivity(intent)
        }
    }
    
    inner class PunchRecordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val itemId: TextView = itemView.findViewById(R.id.datarecord_viewholder_id)
        val itemID: TextView = itemView.findViewById(R.id.punch_id)
        val itemInTime: TextView = itemView.findViewById(R.id.punch_in)
        val itemOutTime: TextView = itemView.findViewById(R.id.punch_out)
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PunchRecordViewHolder {
        val itemView = inflater.inflate(R.layout.punch_list, parent, false)
        return PunchRecordViewHolder(itemView)
    }
    
    override fun onBindViewHolder(holder: PunchRecordViewHolder, position: Int) {
        val current = itemsList[position]
        // Needed: will be referenced in the View.OnClickListener above
        holder.itemView.tag = current
        with(holder) {
            // Set UI values
            itemId.text = current.id.toString()
            // itemRecord.text = current.record
            itemID.text = current.empid
            itemInTime.text = current.intime
            itemOutTime.text = current.outtime
            // Set handlers
            itemView.setOnClickListener(onClickListener)
        }
    }
    
    internal fun setItems(items: List<PunchRecord>) {
        this.itemsList = items.toMutableList()
        notifyDataSetChanged()
    }
    
    override fun getItemCount() = itemsList.size
    
    companion object {
        const val DATA_RECORD_ID : String = "datarecord_id"
    }
    

    タイムアクティビティで.KTの活動は、ビジネスロジックを見つけるために時間とアウト時間を追加します.
    ` class timeactivity : appcompatactivit (), datepickerDialog .OnDataSetListener , TimePickerDialog.ontimesetlistener { }
    private lateinit var dataViewModel: PunchViewModel
    private var recordId: Long = 0L
    private var isEdit: Boolean = false
    
    var day = 0
    var month = 0
    var year = 0
    var hour = 0
    var minute = 0
    
    var savedDay = 0
    var savedMonth = 0
    var savedYear = 0
    var savedHour = 0
    var savedMinute = 0
    
    var isInTime : Boolean = false
    var isOutTime : Boolean = false
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_time)
    
        dataViewModel = ViewModelProvider(this)[PunchViewModel::class.java]
        if (intent.hasExtra(PunchAdapter.DATA_RECORD_ID)) {
            recordId = intent.getLongExtra(PunchAdapter.DATA_RECORD_ID, 0L)
            dataViewModel.get(recordId).observe(this, Observer {
                val viewId = findViewById<TextView>(R.id.datarecord_id)
                val viewEmpid = findViewById<EditText>(R.id.edtpunch_id)
                val viewInTime = findViewById<EditText>(R.id.edtpunch_intime)
                val viewOutTime = findViewById<EditText>(R.id.edtpunch_outtime)
                if (it != null) {
                    // populate with data
                    viewId.text = it.id.toString()
                    viewEmpid.setText(it.empid)
                    viewInTime.setText(it.intime)
                    viewOutTime.setText(it.outtime)
                }
            })
            isEdit = true
        }
    
        edtpunch_intime.setOnClickListener{
            isInTime = true
            isOutTime = false
            getDateTimeCalendar()
            DatePickerDialog(this,this,year,month,day ).show()
        }
    
        edtpunch_outtime.setOnClickListener{
            getDateTimeCalendar()
            isInTime = false
            isOutTime = true
            DatePickerDialog(this,this,year, month, day ).show()
        }
    
        btnpunch_save.setOnClickListener { view ->
            val id = 0L
            val mEmpid = edtpunch_id.text.toString()
            val mInTime = edtpunch_intime.text.toString()
            val mOutTime = edtpunch_outtime.text.toString()
            if (mEmpid.isBlank() ) {
                Toast.makeText(this, "Employee ID is blank", Toast.LENGTH_SHORT).show()
            }
            else if (mInTime.isBlank()) {
                Toast.makeText(this, "In Time is blank", Toast.LENGTH_SHORT).show()
            }
            else if(mOutTime.isBlank()) {
                Toast.makeText(this, "Out Time is blank", Toast.LENGTH_SHORT).show()
            }
            else {
                val item = PunchRecord(id = id, empid = mEmpid, intime = mInTime, outtime = mOutTime)
                dataViewModel.insert(item)
                finish()
            }
        }
        btnpunch_update.setOnClickListener { view ->
            val id = datarecord_id.text.toString().toLong()
            val nEmpid = edtpunch_id.text.toString()
            val nInTime = edtpunch_intime.text.toString()
            val nOutTime = edtpunch_outtime.text.toString()
            if (nEmpid.isBlank() && nInTime.isBlank() && nOutTime.isBlank()) {
                Toast.makeText(this, "Empty data is not allowed", Toast.LENGTH_SHORT).show()
            } else {
                val item = PunchRecord(id = id, empid = nEmpid, intime = nInTime, outtime = nOutTime)
                dataViewModel.update(item)
                finish()
            }
        }
        btnpunch_delete.setOnClickListener {
            val id = datarecord_id.text.toString().toLong()
            val nEmpid = edtpunch_id.text.toString()
            val nInTime = edtpunch_intime.text.toString()
            val nOutTime = edtpunch_outtime.text.toString()
            val item = PunchRecord( id =id, empid = nEmpid, intime = nInTime, outtime = nOutTime)
            dataViewModel.delete(item)
            finish()
        }
    
    }
    
    private fun getDateTimeCalendar(){
        val cal: Calendar = Calendar.getInstance()
        day = cal.get(Calendar.DAY_OF_MONTH)
        month = cal.get(Calendar.MONTH)
        year = cal.get(Calendar.YEAR)
        hour = cal.get(Calendar.HOUR)
        minute = cal.get(Calendar.MINUTE)
    }
    
    override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
        savedDay = dayOfMonth
        savedMonth = month
        savedYear = year
        getDateTimeCalendar()
        TimePickerDialog(this, this, hour, minute, true).show()
    }
    override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
        savedHour = hourOfDay
        savedMinute = minute
        if (isInTime) {
            edtpunch_intime.setText("$savedDay-$savedMonth-$savedYear, $savedHour:$savedMinute")
        }
        if (isOutTime) {
            edtpunch_outtime.setText("$savedDay-$savedMonth-$savedYear, $savedHour:$savedMinute")
        }
    }
    

    ログインしてください.XMLのUI画面を作成することができます.
    「?xml version ="1.0 "encoding = "utf - 8 "?
    xmlns : app ="http://schemas.android.com/apk/res-auto"
    xmlns :ツール=http://schemas.android.com/tools"
    アンドロイド:LayoutCount幅=「マッチした親」
    アンドロイド:レイアウトの高さ
    アンドロイドの向き
    ツール:コンテキスト="ROomDatabase
    <Button
        android:id="@+id/btn_punch"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:textSize="18dp"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="20dp"
        android:layout_gravity="center_horizontal"
        android:textAllCaps="false"
        android:text="Click to Punch"/>
    
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
    `
    を返します.XMLのUI画面を作成することができます.
    「?xml version ="1.0 "encoding = "utf - 8 "?
    xmlns : app ="http://schemas.android.com/apk/res-auto"
    xmlns :ツール=http://schemas.android.com/tools"
    アンドロイド:LayoutCount幅=「マッチした親」
    アンドロイド:レイアウトの高さ
    アンドロイドの向き
    ツール:コンテキスト="roomdatabase . timeactivity "
    <TextView
        android:id="@+id/datarecord_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_gravity="left"
        android:hint="id "
        android:padding="5dp"
        android:layout_marginLeft="10dp"
        android:textSize="18sp"
        android:textColor="@color/black" />
    <EditText
        android:id="@+id/edtpunch_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_gravity="left"
        android:hint="EmpID: "
        android:padding="5dp"
        android:layout_marginLeft="10dp"
        android:textSize="18sp"
        android:textColor="@color/black" />
    <EditText
        android:id="@+id/edtpunch_intime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_gravity="left"
        android:hint="In Time:  "
        android:textSize="18sp"
        android:padding="5dp"
        android:layout_marginLeft="10dp"
        android:textColor="@color/black" />
    <EditText
        android:id="@+id/edtpunch_outtime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_gravity="left"
        android:hint="Out Time:  "
        android:textSize="18sp"
        android:padding="5dp"
        android:layout_marginLeft="10dp"
        android:textColor="@color/black" />
    <Button
        android:id="@+id/btnpunch_save"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:textSize="18dp"
        android:textAllCaps="false"
        android:layout_marginTop="5dp"
        android:text="Save"/>
    <Button
        android:id="@+id/btnpunch_update"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:textSize="18dp"
        android:textAllCaps="false"
        android:layout_marginTop="5dp"
        android:text="Update"/>
    <Button
        android:id="@+id/btnpunch_delete"
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:textSize="18dp"
        android:textAllCaps="false"
        android:layout_marginTop="5dp"
        android:text="Delete"/>
    
    `
    Punchchenリストで.XMLは、カスタマイズされたアイテムのUI画面を作成することができます.
    「?xml version ="1.0 "encoding = "utf - 8 "?
    アンドロイド:LayoutCount幅=「マッチした親」
    アンドロイド:LayoutRange高さ=「ラップされた内容」
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">
        <TextView
            android:id="@+id/datarecord_viewholder_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="10dp"
            android:textSize="18sp"
            android:text="id: "
            android:textColor="@color/black"
            android:textStyle="bold" />
        <TextView
            android:id="@+id/punch_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:layout_marginTop="10dp"
            android:textStyle="bold"
            android:textColor="@color/black"
            android:text="ID: " />
        <TextView
            android:id="@+id/punch_in"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:layout_marginTop="10dp"
            android:textStyle="bold"
            android:textColor="@color/black"
            android:text="IN Time: " />
        <TextView
            android:id="@+id/punch_out"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:layout_marginTop="10dp"
            android:textStyle="bold"
            android:textColor="@color/black"
            android:text="OUT Time: " />
    </LinearLayout>
    
    `
    デモ


    ヒントとトリック
  • あなたはすでにHuawei開発者として登録されていることを確認します.
  • Minsdkのバージョンを24またはそれ以降に設定し、そうでない場合はAndAndManifestマージ問題を取得します.
  • AGConnectサービスを追加したことを確認します.アプリケーションフォルダにJSONファイル.
  • 確実にSHA - 256指紋を追加したことを確認します.
  • すべての依存関係が適切に追加されるようにしてください.
  • 結論
    本論文では,ルームデータベースによるユーザの時間と外出時間の入力方法について学び,イベント追跡のための解析キットを統合できる.
    この記事を読んでください.あなたがそれが役に立つとわかるならば、好きとコメントを提供してください.
    リファレンス
    分析キット
    分析キット
    Add Configuration