Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
NewParkAPP
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
YONG-LIN SU
NewParkAPP
Commits
2c215f50
Commit
2c215f50
authored
Jul 29, 2022
by
YONG-LIN SU
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增案件功能 及 拍照儲存壓制功能
parent
108b1de2
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
604 additions
and
22 deletions
+604
-22
ModifyPhoto.java
app/src/main/java/ecom/android/newparkapp/ModifyPhoto.java
+74
-0
ConvertBindingAdapter.java
...com/android/newparkapp/adapter/ConvertBindingAdapter.java
+3
-0
CasePhotoDao.java
...c/main/java/ecom/android/newparkapp/dao/CasePhotoDao.java
+32
-0
InfoDatabase.java
...n/java/ecom/android/newparkapp/database/InfoDatabase.java
+4
-1
Case.java
app/src/main/java/ecom/android/newparkapp/entity/Case.java
+60
-10
CasePhoto.java
...c/main/java/ecom/android/newparkapp/entity/CasePhoto.java
+33
-0
CaseStatus.java
.../main/java/ecom/android/newparkapp/entity/CaseStatus.java
+8
-0
Road.java
app/src/main/java/ecom/android/newparkapp/entity/Road.java
+4
-0
Space.java
app/src/main/java/ecom/android/newparkapp/entity/Space.java
+10
-0
SpaceRate.java
...c/main/java/ecom/android/newparkapp/entity/SpaceRate.java
+32
-1
SpaceStatus.java
...main/java/ecom/android/newparkapp/entity/SpaceStatus.java
+32
-1
SpaceType.java
...c/main/java/ecom/android/newparkapp/entity/SpaceType.java
+32
-1
VehicleType.java
...main/java/ecom/android/newparkapp/entity/VehicleType.java
+4
-0
InfoRepository.java
...va/ecom/android/newparkapp/repository/InfoRepository.java
+3
-0
MainActivity.java
.../main/java/ecom/android/newparkapp/view/MainActivity.java
+12
-0
T02StartActivity.java
...n/java/ecom/android/newparkapp/view/T02StartActivity.java
+82
-0
T02StartViewModel.java
.../ecom/android/newparkapp/viewModel/T02StartViewModel.java
+175
-7
activity_t02_start.xml
app/src/main/res/layout/activity_t02_start.xml
+1
-1
999
相關文件/占存檔/999
+1
-0
99B17V00189.txt
相關文件/占存檔/99B17V00189.txt
+1
-0
A999-20220729
相關文件/占存檔/A999-20220729
+1
-0
No files found.
app/src/main/java/ecom/android/newparkapp/ModifyPhoto.java
0 → 100644
View file @
2c215f50
package
ecom
.
android
.
newparkapp
;
import
android.graphics.Bitmap
;
import
android.graphics.BitmapFactory
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.graphics.Paint
;
import
android.graphics.Rect
;
import
android.graphics.Typeface
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
java.util.Calendar
;
public
class
ModifyPhoto
implements
Runnable
{
private
final
String
path
;
public
ModifyPhoto
(
String
path
)
{
this
.
path
=
path
;
}
@Override
public
void
run
()
{
//Log.d("ModifyPhoto", " Begins Work : " + Thread.currentThread().getName());
BitmapFactory
.
Options
options
=
new
BitmapFactory
.
Options
();
options
.
inSampleSize
=
2
;
Bitmap
bitmap
=
BitmapFactory
.
decodeFile
(
path
,
options
);
bitmap
=
Common
.
turnPictureDegree
(
bitmap
,
path
);
int
width
=
bitmap
.
getWidth
();
int
height
=
bitmap
.
getHeight
();
Bitmap
icon
=
Bitmap
.
createBitmap
(
width
,
height
,
Bitmap
.
Config
.
ARGB_8888
);
Canvas
canvas
=
new
Canvas
(
icon
);
Paint
photoPaint
=
new
Paint
();
photoPaint
.
setDither
(
true
);
photoPaint
.
setFilterBitmap
(
true
);
Rect
src
=
new
Rect
(
0
,
0
,
bitmap
.
getWidth
(),
bitmap
.
getHeight
());
Rect
dst
=
new
Rect
(
0
,
0
,
width
,
height
);
canvas
.
drawBitmap
(
bitmap
,
src
,
dst
,
photoPaint
);
Paint
text
=
new
Paint
(
Paint
.
ANTI_ALIAS_FLAG
|
Paint
.
DEV_KERN_TEXT_FLAG
);
Paint
stroke
=
new
Paint
(
Paint
.
ANTI_ALIAS_FLAG
|
Paint
.
DEV_KERN_TEXT_FLAG
);
int
x
=
width
/
38
;
int
y
=
width
/
16
;
text
.
setTextSize
(
y
);
text
.
setTypeface
(
Typeface
.
DEFAULT_BOLD
);
text
.
setColor
(
Color
.
WHITE
);
text
.
setStyle
(
Paint
.
Style
.
FILL
);
//文字本體
stroke
.
setTextSize
(
y
);
stroke
.
setTypeface
(
Typeface
.
DEFAULT_BOLD
);
stroke
.
setColor
(
Color
.
BLACK
);
stroke
.
setStyle
(
Paint
.
Style
.
STROKE
);
//文字外框
stroke
.
setStrokeWidth
((
float
)
width
/
284
);
String
nowTime
=
Common
.
getDateAndTime
(
Calendar
.
getInstance
());
canvas
.
drawText
(
nowTime
,
x
,
y
,
text
);
canvas
.
drawText
(
nowTime
,
x
,
y
,
stroke
);
canvas
.
save
();
canvas
.
restore
();
try
(
FileOutputStream
out
=
new
FileOutputStream
(
path
))
{
icon
.
compress
(
Bitmap
.
CompressFormat
.
JPEG
,
60
,
out
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
if
(!
bitmap
.
isRecycled
())
{
bitmap
.
recycle
();
}
if
(!
icon
.
isRecycled
())
{
icon
.
recycle
();
}
}
//Log.d("ModifyPhoto", " Ends Work : " + Thread.currentThread().getName());
}
}
app/src/main/java/ecom/android/newparkapp/adapter/ConvertBindingAdapter.java
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
adapter
;
import
android.widget.Button
;
import
android.widget.TextView
;
import
androidx.databinding.BindingAdapter
;
...
...
@@ -7,6 +8,8 @@ import androidx.databinding.BindingAdapter;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
ecom.android.newparkapp.entity.Case
;
public
class
ConvertBindingAdapter
{
@BindingAdapter
(
"date2TimeString"
)
...
...
app/src/main/java/ecom/android/newparkapp/dao/CasePhotoDao.java
0 → 100644
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
dao
;
import
androidx.lifecycle.LiveData
;
import
androidx.room.Dao
;
import
androidx.room.Delete
;
import
androidx.room.Insert
;
import
androidx.room.Query
;
import
java.util.List
;
import
ecom.android.newparkapp.entity.CasePhoto
;
@Dao
public
interface
CasePhotoDao
{
@Query
(
"SELECT * FROM casephoto"
)
List
<
CasePhoto
>
getAll
();
@Query
(
"SELECT * FROM casephoto"
)
LiveData
<
List
<
CasePhoto
>>
getAllLiveData
();
@Query
(
"SELECT * FROM casephoto WHERE case_billing_number2 IN (:billingNumber2s)"
)
List
<
CasePhoto
>
loadAllByIds
(
String
[]
billingNumber2s
);
@Insert
void
insertAll
(
CasePhoto
...
casePhotos
);
@Delete
void
delete
(
CasePhoto
casephoto
);
@Query
(
"DELETE FROM casephoto"
)
void
deleteAll
();
}
app/src/main/java/ecom/android/newparkapp/database/InfoDatabase.java
View file @
2c215f50
...
...
@@ -9,6 +9,7 @@ import androidx.room.TypeConverters;
import
ecom.android.newparkapp.R
;
import
ecom.android.newparkapp.dao.CaseDao
;
import
ecom.android.newparkapp.dao.CasePhotoDao
;
import
ecom.android.newparkapp.dao.RoadDao
;
import
ecom.android.newparkapp.dao.SpaceDao
;
import
ecom.android.newparkapp.dao.SpaceRateDao
;
...
...
@@ -20,6 +21,7 @@ import ecom.android.newparkapp.dao.VehicleBrandDao;
import
ecom.android.newparkapp.dao.VehicleColorDao
;
import
ecom.android.newparkapp.dao.VehicleTypeDao
;
import
ecom.android.newparkapp.entity.Case
;
import
ecom.android.newparkapp.entity.CasePhoto
;
import
ecom.android.newparkapp.entity.LocationConverter
;
import
ecom.android.newparkapp.entity.Road
;
import
ecom.android.newparkapp.entity.Space
;
...
...
@@ -34,11 +36,12 @@ import ecom.android.newparkapp.entity.VehicleColor;
import
ecom.android.newparkapp.entity.VehicleType
;
// DataBase 一個資料庫一個,並涵蓋多個資料表
@Database
(
entities
=
{
Case
.
class
,
Road
.
class
,
Space
.
class
,
SpaceRate
.
class
,
SpaceStatus
.
class
,
SpaceType
.
class
,
User
.
class
,
UserPermission
.
class
,
VehicleBrand
.
class
,
VehicleColor
.
class
,
VehicleType
.
class
},
@Database
(
entities
=
{
Case
.
class
,
CasePhoto
.
class
,
Road
.
class
,
Space
.
class
,
SpaceRate
.
class
,
SpaceStatus
.
class
,
SpaceType
.
class
,
User
.
class
,
UserPermission
.
class
,
VehicleBrand
.
class
,
VehicleColor
.
class
,
VehicleType
.
class
},
version
=
1
)
@TypeConverters
({
LocationConverter
.
class
,
TimestampConverter
.
class
})
public
abstract
class
InfoDatabase
extends
RoomDatabase
{
public
abstract
CaseDao
caseDao
();
public
abstract
CasePhotoDao
casePhotoDao
();
public
abstract
RoadDao
roadDao
();
public
abstract
SpaceDao
spaceDao
();
public
abstract
SpaceRateDao
spaceRateDao
();
...
...
app/src/main/java/ecom/android/newparkapp/entity/Case.java
View file @
2c215f50
...
...
@@ -9,7 +9,10 @@ import androidx.room.Entity;
import
androidx.room.Ignore
;
import
androidx.room.PrimaryKey
;
import
java.text.DateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Locale
;
@Entity
public
class
Case
{
...
...
@@ -28,9 +31,6 @@ public class Case {
@ColumnInfo
(
name
=
"case_time"
)
public
Date
caseTime
;
// 開單時間
@Embedded
(
prefix
=
"road_"
)
public
Road
road
;
@Embedded
(
prefix
=
"space_"
)
public
Space
space
;
...
...
@@ -47,13 +47,13 @@ public class Case {
public
VehicleBrand
vehicleBrand
;
@ColumnInfo
(
name
=
"period_hour"
)
public
float
periodHour
;
public
float
periodHour
;
// 停留幾個小時,根據該車格計時單位計算
@ColumnInfo
(
name
=
"final_expenses"
)
public
int
finalExpenses
;
public
int
finalExpenses
;
// 最終停車費金額 = 總時數 * 費率
@ColumnInfo
(
name
=
"location"
)
public
Location
location
;
public
Location
location
;
// gps 座標
@ColumnInfo
(
name
=
"bill_status"
)
public
int
billStatus
;
...
...
@@ -62,10 +62,10 @@ public class Case {
public
int
photoCount
;
@ColumnInfo
(
name
=
"update_date"
)
public
Date
updateDate
;
public
Date
updateDate
;
// 更新日期
@ColumnInfo
(
name
=
"final_time"
)
public
Date
finalTime
;
public
Date
finalTime
;
// 最後一次續單時間
@ColumnInfo
(
name
=
"auto_pay"
)
public
Boolean
autoPay
;
// 自動扣款
...
...
@@ -88,13 +88,15 @@ public class Case {
@Ignore
public
String
uploadPath
;
public
Case
(
String
billingNumber2
,
String
billingNumber1
,
User
user
,
Date
terminateDate
,
Date
caseTime
,
Road
road
,
Space
space
,
String
plateNumber
,
VehicleType
vehicleType
,
VehicleColor
vehicleColor
,
VehicleBrand
vehicleBrand
,
float
periodHour
,
int
finalExpenses
,
Location
location
,
int
billStatus
,
int
photoCount
,
Date
updateDate
,
Date
finalTime
,
Boolean
autoPay
,
int
agency
,
String
shiftId
)
{
@Ignore
public
CaseStatus
caseStatus
;
public
Case
(
String
billingNumber2
,
String
billingNumber1
,
User
user
,
Date
terminateDate
,
Date
caseTime
,
Space
space
,
String
plateNumber
,
VehicleType
vehicleType
,
VehicleColor
vehicleColor
,
VehicleBrand
vehicleBrand
,
float
periodHour
,
int
finalExpenses
,
Location
location
,
int
billStatus
,
int
photoCount
,
Date
updateDate
,
Date
finalTime
,
Boolean
autoPay
,
int
agency
,
String
shiftId
)
{
this
.
billingNumber2
=
billingNumber2
;
this
.
billingNumber1
=
billingNumber1
;
this
.
user
=
user
;
this
.
terminateDate
=
terminateDate
;
this
.
caseTime
=
caseTime
;
this
.
road
=
road
;
this
.
space
=
space
;
this
.
plateNumber
=
plateNumber
;
this
.
vehicleType
=
vehicleType
;
...
...
@@ -114,4 +116,52 @@ public class Case {
public
Case
(){
}
/**
* 早班 晚班 標記
* @return A 或 B
*/
public
String
getShift
(){
// TODO: 2022/7/29 資料庫新增早晚班參照後,取消該方法
return
"A"
;
}
public
String
getUploadFileName
()
{
return
billingNumber2
+
".txt"
;
}
/**
* 交換用檔案,串連各項資訊獲得
* @return 交換用檔案字串 A999;99B17V00189;20220817;10:43;A 中山路A;A216 2 1 中山路A;01 自小客;8052-LZ; ; ;0.5;25;Lat:24.1434911 Lon:120.7285887;1;1;
*/
public
String
getDetailString
()
{
DateFormat
terminateDateFormat
=
new
SimpleDateFormat
(
"yyyymmdd"
);
String
terminateDateString
=
terminateDateFormat
.
format
(
terminateDate
);
// 20220817
DateFormat
caseTimeFormat
=
new
SimpleDateFormat
(
"HH:mm"
);
String
caseTimeString
=
caseTimeFormat
.
format
(
caseTime
);
// 10:43
// TODO: 2022/7/29 加入GPS座標功能後,修改該處假資料
//String locationString = String.format("Lat:%f Lon:%f", location.getLatitude(), location.getLongitude()); // Lat:24.1434911 Lon:120.7285887
String
locationString
=
"Lat:24.1434911 Lon:120.7285887"
;
return
String
.
format
(
Locale
.
TAIWAN
,
"%s%s;%s;%s;%s;%s;%s;%s;%s;%s;%s;%.1f;%d;%s;%s;%d;\r\n"
,
getShift
(),
user
.
id
,
billingNumber2
,
terminateDateString
,
caseTimeString
,
space
.
road
.
getCombineInfo
(),
space
.
getCombineInfo
(),
vehicleType
.
getCombineInfo
(),
plateNumber
,
" "
,
// Car Color
" "
,
// Car Brand
periodHour
,
finalExpenses
,
locationString
,
billStatus
,
photoCount
);
}
}
app/src/main/java/ecom/android/newparkapp/entity/CasePhoto.java
0 → 100644
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
entity
;
import
static
androidx
.
room
.
ForeignKey
.
CASCADE
;
import
androidx.room.ColumnInfo
;
import
androidx.room.Entity
;
import
androidx.room.ForeignKey
;
import
androidx.room.PrimaryKey
;
@Entity
(
foreignKeys
=
@ForeignKey
(
entity
=
Case
.
class
,
parentColumns
=
"billingNumber2"
,
childColumns
=
"case_billing_number2"
,
onDelete
=
CASCADE
)
)
public
class
CasePhoto
{
@PrimaryKey
public
int
id
;
@ColumnInfo
(
name
=
"case_billing_number2"
)
public
String
caseBillingNumber2
;
@ColumnInfo
(
name
=
"photo_path"
)
public
String
photoPath
;
@ColumnInfo
(
name
=
"plate_number"
)
public
String
plateNumber
;
public
CasePhoto
(
int
id
,
String
caseBillingNumber2
,
String
photoPath
,
String
plateNumber
)
{
this
.
id
=
id
;
this
.
caseBillingNumber2
=
caseBillingNumber2
;
this
.
photoPath
=
photoPath
;
this
.
plateNumber
=
plateNumber
;
}
}
app/src/main/java/ecom/android/newparkapp/entity/CaseStatus.java
0 → 100644
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
entity
;
public
enum
CaseStatus
{
NEW
,
//尚未儲存之新案件
LIST
,
//已儲存之案件
CHANGED
,
//已儲存但有異動過之案件
LOCK
//註銷之案件
}
app/src/main/java/ecom/android/newparkapp/entity/Road.java
View file @
2c215f50
...
...
@@ -51,4 +51,8 @@ public class Road implements Parcelable {
return
new
Road
[
size
];
}
};
public
String
getCombineInfo
()
{
return
String
.
format
(
"%s %s"
,
id
,
name
);
}
}
app/src/main/java/ecom/android/newparkapp/entity/Space.java
View file @
2c215f50
...
...
@@ -52,18 +52,24 @@ public class Space implements Parcelable {
protected
Space
(
Parcel
in
)
{
id
=
in
.
readString
();
road
=
in
.
readParcelable
(
Road
.
class
.
getClassLoader
());
spaceType
=
in
.
readParcelable
(
SpaceType
.
class
.
getClassLoader
());
fee
=
in
.
readInt
();
spaceRate
=
in
.
readParcelable
(
SpaceRate
.
class
.
getClassLoader
());
latitude
=
in
.
readFloat
();
longitude
=
in
.
readFloat
();
spaceStatus
=
in
.
readParcelable
(
SpaceStatus
.
class
.
getClassLoader
());
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeString
(
id
);
dest
.
writeParcelable
(
road
,
flags
);
dest
.
writeParcelable
(
spaceType
,
flags
);
dest
.
writeInt
(
fee
);
dest
.
writeParcelable
(
spaceRate
,
flags
);
dest
.
writeFloat
(
latitude
);
dest
.
writeFloat
(
longitude
);
dest
.
writeParcelable
(
spaceStatus
,
flags
);
}
@Override
...
...
@@ -82,4 +88,8 @@ public class Space implements Parcelable {
return
new
Space
[
size
];
}
};
public
String
getCombineInfo
()
{
return
String
.
format
(
"%s %s %s %s"
,
id
,
spaceRate
.
id
,
spaceType
.
id
,
road
.
name
);
}
}
app/src/main/java/ecom/android/newparkapp/entity/SpaceRate.java
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
entity
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
androidx.room.ColumnInfo
;
import
androidx.room.Entity
;
import
androidx.room.PrimaryKey
;
...
...
@@ -8,7 +11,7 @@ import androidx.room.PrimaryKey;
* 停車收費頻率資料表
*/
@Entity
public
class
SpaceRate
{
public
class
SpaceRate
implements
Parcelable
{
@PrimaryKey
public
int
id
;
...
...
@@ -20,4 +23,32 @@ public class SpaceRate {
this
.
id
=
id
;
this
.
perHours
=
perHours
;
}
protected
SpaceRate
(
Parcel
in
)
{
id
=
in
.
readInt
();
perHours
=
in
.
readFloat
();
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
id
);
dest
.
writeFloat
(
perHours
);
}
@Override
public
int
describeContents
()
{
return
0
;
}
public
static
final
Creator
<
SpaceRate
>
CREATOR
=
new
Creator
<
SpaceRate
>()
{
@Override
public
SpaceRate
createFromParcel
(
Parcel
in
)
{
return
new
SpaceRate
(
in
);
}
@Override
public
SpaceRate
[]
newArray
(
int
size
)
{
return
new
SpaceRate
[
size
];
}
};
}
app/src/main/java/ecom/android/newparkapp/entity/SpaceStatus.java
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
entity
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
androidx.room.ColumnInfo
;
import
androidx.room.Entity
;
import
androidx.room.PrimaryKey
;
@Entity
public
class
SpaceStatus
{
public
class
SpaceStatus
implements
Parcelable
{
@PrimaryKey
public
int
id
;
...
...
@@ -16,4 +19,32 @@ public class SpaceStatus {
this
.
id
=
id
;
this
.
name
=
name
;
}
protected
SpaceStatus
(
Parcel
in
)
{
id
=
in
.
readInt
();
name
=
in
.
readString
();
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
id
);
dest
.
writeString
(
name
);
}
@Override
public
int
describeContents
()
{
return
0
;
}
public
static
final
Creator
<
SpaceStatus
>
CREATOR
=
new
Creator
<
SpaceStatus
>()
{
@Override
public
SpaceStatus
createFromParcel
(
Parcel
in
)
{
return
new
SpaceStatus
(
in
);
}
@Override
public
SpaceStatus
[]
newArray
(
int
size
)
{
return
new
SpaceStatus
[
size
];
}
};
}
app/src/main/java/ecom/android/newparkapp/entity/SpaceType.java
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
entity
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
androidx.room.ColumnInfo
;
import
androidx.room.Entity
;
import
androidx.room.PrimaryKey
;
...
...
@@ -8,7 +11,7 @@ import androidx.room.PrimaryKey;
* 停車格類型資料表
*/
@Entity
public
class
SpaceType
{
public
class
SpaceType
implements
Parcelable
{
@PrimaryKey
public
int
id
;
...
...
@@ -19,4 +22,32 @@ public class SpaceType {
this
.
id
=
id
;
this
.
name
=
name
;
}
protected
SpaceType
(
Parcel
in
)
{
id
=
in
.
readInt
();
name
=
in
.
readString
();
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
id
);
dest
.
writeString
(
name
);
}
@Override
public
int
describeContents
()
{
return
0
;
}
public
static
final
Creator
<
SpaceType
>
CREATOR
=
new
Creator
<
SpaceType
>()
{
@Override
public
SpaceType
createFromParcel
(
Parcel
in
)
{
return
new
SpaceType
(
in
);
}
@Override
public
SpaceType
[]
newArray
(
int
size
)
{
return
new
SpaceType
[
size
];
}
};
}
app/src/main/java/ecom/android/newparkapp/entity/VehicleType.java
View file @
2c215f50
...
...
@@ -50,4 +50,8 @@ public class VehicleType implements Parcelable {
parcel
.
writeInt
(
id
);
parcel
.
writeString
(
name
);
}
public
String
getCombineInfo
()
{
return
String
.
format
(
"%s %s"
,
id
,
name
);
}
}
app/src/main/java/ecom/android/newparkapp/repository/InfoRepository.java
View file @
2c215f50
...
...
@@ -7,6 +7,7 @@ import java.util.concurrent.Executors;
import
ecom.android.newparkapp.R
;
import
ecom.android.newparkapp.dao.CaseDao
;
import
ecom.android.newparkapp.dao.CasePhotoDao
;
import
ecom.android.newparkapp.dao.RoadDao
;
import
ecom.android.newparkapp.dao.SpaceDao
;
import
ecom.android.newparkapp.dao.SpaceRateDao
;
...
...
@@ -38,6 +39,7 @@ public class InfoRepository {
public
RoadDao
roadDao
;
public
SpaceDao
spaceDao
;
public
CaseDao
caseDao
;
public
CasePhotoDao
casePhotoDao
;
public
InfoRepository
(
Application
application
)
{
infoDatabase
=
InfoDatabase
.
getInstance
(
application
);
...
...
@@ -55,6 +57,7 @@ public class InfoRepository {
roadDao
=
infoDatabase
.
roadDao
();
spaceDao
=
infoDatabase
.
spaceDao
();
caseDao
=
infoDatabase
.
caseDao
();
casePhotoDao
=
infoDatabase
.
casePhotoDao
();
executorService
=
Executors
.
newFixedThreadPool
(
application
.
getResources
().
getInteger
(
R
.
integer
.
number_db_thread_pool
));
}
...
...
app/src/main/java/ecom/android/newparkapp/view/MainActivity.java
View file @
2c215f50
...
...
@@ -46,10 +46,13 @@ public class MainActivity extends AppCompatActivity {
dataBinding
.
setUserViewModel
(
userViewModel
);
// 註冊權限請求結果處理
resultLauncherRegister
();
// 檢查權限
permissionRequest
();
// 監聽權限驗證變化
// 有權限再綁定按鈕功能
hasPermissions
.
observe
(
this
,
has
->
{
if
(
has
){
eventBinding
();
...
...
@@ -57,6 +60,9 @@ public class MainActivity extends AppCompatActivity {
});
}
/**
* 權限請求方法
*/
private
void
permissionRequest
(){
// 參考資料 https://developer.android.com/training/permissions/requesting
hasPermissions
.
setValue
(
false
);
...
...
@@ -67,6 +73,9 @@ public class MainActivity extends AppCompatActivity {
}
}
/**
* @return 檢查所有權限
*/
private
boolean
checkPermissions
(){
boolean
ret
=
true
;
for
(
String
permission
:
permissions
){
...
...
@@ -78,6 +87,9 @@ public class MainActivity extends AppCompatActivity {
return
ret
;
}
/**
* 註冊 registerForActivityResult 事件處理
*/
private
void
resultLauncherRegister
(){
requestPermissionLauncher
=
registerForActivityResult
(
new
ActivityResultContracts
.
RequestMultiplePermissions
(),
...
...
app/src/main/java/ecom/android/newparkapp/view/T02StartActivity.java
View file @
2c215f50
...
...
@@ -4,15 +4,23 @@ import androidx.activity.result.ActivityResultLauncher;
import
androidx.activity.result.contract.ActivityResultContracts
;
import
androidx.appcompat.app.AlertDialog
;
import
androidx.appcompat.app.AppCompatActivity
;
import
androidx.core.content.FileProvider
;
import
androidx.databinding.DataBindingUtil
;
import
androidx.lifecycle.ViewModelProvider
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.content.pm.ActivityInfo
;
import
android.net.Uri
;
import
android.os.Bundle
;
import
android.os.Environment
;
import
android.provider.MediaStore
;
import
android.widget.Toast
;
import
java.io.File
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Objects
;
...
...
@@ -35,8 +43,11 @@ public class T02StartActivity extends AppCompatActivity {
private
ActivityResultLauncher
vehicleTypeResultLauncher
;
private
ActivityResultLauncher
spaceResultLauncher
;
private
ActivityResultLauncher
plateNumberResultLauncher
;
private
ActivityResultLauncher
takePhotosActivityResultLauncher
;
private
User
currentUser
;
private
File
photoFile
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
...
...
@@ -62,10 +73,16 @@ public class T02StartActivity extends AppCompatActivity {
dataBinding
.
btnVehicleType
.
setOnClickListener
(
v
->
btnVehicleTypeOnClicked
());
dataBinding
.
btnTimeNow
.
setOnClickListener
(
v
->
btnTimeNowOnClicked
());
dataBinding
.
btnPlateNumber
.
setOnClickListener
(
v
->
btnPlateNumberOnClicked
());
dataBinding
.
btnPhotograph
.
setOnClickListener
(
v
->
btnPhotographOnClicked
());
dataBinding
.
btnNewPage
.
setOnClickListener
(
v
->
btnNewPageOnClicked
());
dataBinding
.
btnPageDown
.
setOnClickListener
(
v
->
btnPageDownOnClicked
());
dataBinding
.
btnPageUp
.
setOnClickListener
(
v
->
btnPageUpOnClicked
());
dataBinding
.
btnStartBack
.
setOnClickListener
(
v
->
{
finish
();});
}
private
void
resultLauncherRegister
(){
vehicleTypeResultLauncher
=
registerForActivityResult
(
new
ActivityResultContracts
.
StartActivityForResult
(),
result
->
{
if
(
result
.
getResultCode
()
==
RESULT_OK
&&
result
.
getData
()!=
null
){
VehicleType
selectedVehicleType
=
result
.
getData
().
getParcelableExtra
(
"VehicleType"
);
...
...
@@ -87,9 +104,20 @@ public class T02StartActivity extends AppCompatActivity {
plateNumberResultLauncher
=
registerForActivityResult
(
new
ActivityResultContracts
.
StartActivityForResult
(),
result
->
{
if
(
result
.
getResultCode
()
==
RESULT_OK
&&
result
.
getData
()
!=
null
){
String
plateNumber
=
result
.
getData
().
getStringExtra
(
"PlateNumber"
);
t02StartViewModel
.
setPlateNumber
(
plateNumber
);
}
});
takePhotosActivityResultLauncher
=
registerForActivityResult
(
new
ActivityResultContracts
.
StartActivityForResult
(),
result
->
{
if
(
result
.
getResultCode
()
==
RESULT_OK
){
if
(
photoFile
==
null
){
return
;
}
t02StartViewModel
.
takeNewPhoto
(
photoFile
);
}
});
}
private
void
observeBinding
(){
...
...
@@ -133,4 +161,58 @@ public class T02StartActivity extends AppCompatActivity {
intent
.
setClass
(
this
,
T02KeyInPlateNumberActivity
.
class
);
plateNumberResultLauncher
.
launch
(
intent
);
}
private
void
btnPhotographOnClicked
(){
Case
currentCase
=
t02StartViewModel
.
getCurrentCase
().
getValue
();
Intent
takePhotoIntent
=
new
Intent
(
MediaStore
.
ACTION_IMAGE_CAPTURE
);
takePhotoIntent
.
addFlags
(
Intent
.
FLAG_GRANT_READ_URI_PERMISSION
);
// 檢查是否已取得權限
if
(
takePhotoIntent
.
resolveActivity
(
getPackageManager
())
==
null
)
return
;
String
day
=
new
SimpleDateFormat
(
"yyyyMMdd"
).
format
(
new
Date
());
String
path
=
Environment
.
getExternalStorageDirectory
()
+
getString
(
R
.
string
.
sysDataPhoto_path
)
+
day
;
File
temp
=
new
File
(
path
);
if
(!
temp
.
exists
())
{
if
(!
temp
.
mkdirs
())
{
Toast
.
makeText
(
this
,
"目錄 "
+
temp
.
getName
()
+
" 新增失敗!"
,
Toast
.
LENGTH_LONG
).
show
();
return
;
}
}
photoFile
=
new
File
(
path
,
"/"
+
currentCase
.
billingNumber2
+
currentCase
.
photoCount
+
".jpg"
);
Uri
photoURI
=
FileProvider
.
getUriForFile
(
this
,
"ecom.android.newparkapp.fileprovider"
,
photoFile
);
takePhotoIntent
.
putExtra
(
MediaStore
.
EXTRA_SCREEN_ORIENTATION
,
ActivityInfo
.
SCREEN_ORIENTATION_PORTRAIT
);
takePhotoIntent
.
putExtra
(
MediaStore
.
EXTRA_OUTPUT
,
photoURI
);
takePhotosActivityResultLauncher
.
launch
(
takePhotoIntent
);
}
private
void
btnNewPageOnClicked
(){
if
(!
t02StartViewModel
.
caseDataConfirm
()){
// 資料不完整
AlertDialog
.
Builder
builder
=
new
AlertDialog
.
Builder
(
this
);
builder
.
setTitle
(
"檔案保存"
);
builder
.
setMessage
(
"資料不完整,請重新確認"
);
builder
.
setPositiveButton
(
"清空"
,(
dialogInterface
,
i
)
->
{
t02StartViewModel
.
initCurrentCase
();
});
builder
.
setNegativeButton
(
"返回"
,(
dialogInterface
,
i
)
->
{
dialogInterface
.
dismiss
();
});
builder
.
create
().
show
();
}
else
{
// 資料完整
// 儲存
t02StartViewModel
.
saveCurrentCase
();
}
}
private
void
btnPageDownOnClicked
(){
t02StartViewModel
.
pageDown
();
}
private
void
btnPageUpOnClicked
(){
t02StartViewModel
.
pageUp
();
}
}
\ No newline at end of file
app/src/main/java/ecom/android/newparkapp/viewModel/T02StartViewModel.java
View file @
2c215f50
package
ecom
.
android
.
newparkapp
.
viewModel
;
import
android.app.Application
;
import
android.
content.Context
;
import
android.
media.MediaScannerConnection
;
import
android.os.Environment
;
import
android.widget.Toast
;
import
androidx.annotation.NonNull
;
import
androidx.lifecycle.AndroidViewModel
;
import
androidx.lifecycle.LiveData
;
import
androidx.lifecycle.MutableLiveData
;
import
androidx.lifecycle.ViewModelProvider
;
import
java.io.File
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Locale
;
import
java.util.Map
;
import
ecom.android.newparkapp.Common
;
import
ecom.android.newparkapp.ModifyPhoto
;
import
ecom.android.newparkapp.R
;
import
ecom.android.newparkapp.entity.Case
;
import
ecom.android.newparkapp.entity.CasePhoto
;
import
ecom.android.newparkapp.entity.CaseStatus
;
import
ecom.android.newparkapp.entity.Road
;
import
ecom.android.newparkapp.entity.Space
;
import
ecom.android.newparkapp.entity.User
;
import
ecom.android.newparkapp.entity.VehicleBrand
;
import
ecom.android.newparkapp.entity.VehicleColor
;
import
ecom.android.newparkapp.entity.VehicleType
;
import
ecom.android.newparkapp.repository.InfoRepository
;
...
...
@@ -31,12 +33,16 @@ import ecom.android.newparkapp.repository.InfoRepository;
public
class
T02StartViewModel
extends
AndroidViewModel
{
private
MutableLiveData
<
Case
>
currentCase
=
new
MutableLiveData
<>();
private
List
<
Case
>
cases
;
private
int
caseCursor
=
0
;
private
LiveData
<
List
<
VehicleType
>>
vehicleTypes
;
private
LiveData
<
List
<
Road
>>
roads
;
private
LiveData
<
List
<
Space
>>
spaces
;
private
InfoRepository
infoRepository
;
private
MutableLiveData
<
User
>
currentUser
=
new
MutableLiveData
<>();
private
List
<
CasePhoto
>
tempCasePhoto
=
new
ArrayList
<>();
public
T02StartViewModel
(
@NonNull
Application
application
)
{
super
(
application
);
...
...
@@ -45,6 +51,7 @@ public class T02StartViewModel extends AndroidViewModel {
vehicleTypes
=
infoRepository
.
vehicleTypeDao
.
getAllLiveData
();
roads
=
infoRepository
.
roadDao
.
getAllLiveData
();
spaces
=
infoRepository
.
spaceDao
.
getAllLiveData
();
cases
=
infoRepository
.
caseDao
.
getAll
();
}
public
LiveData
<
List
<
VehicleType
>>
getVehicleTypes
(){
...
...
@@ -63,9 +70,44 @@ public class T02StartViewModel extends AndroidViewModel {
public
void
setSpace
(
Space
space
){
Case
tempCase
=
currentCase
.
getValue
();
tempCase
.
space
=
space
;
// 取得車格後,更新費用及時間
if
(
tempCase
.
caseStatus
==
CaseStatus
.
NEW
){
int
addCount
=
calcPeriodHourCount
(
tempCase
);
tempCase
.
periodHour
=
addCount
*
space
.
spaceRate
.
perHours
;
tempCase
.
finalExpenses
=
addCount
*
space
.
fee
;
}
currentCase
.
setValue
(
tempCase
);
}
/**
* 計算 累加 時數的次數
* @param thisCase 當前案件
* @return
*/
private
int
calcPeriodHourCount
(
Case
thisCase
){
int
new_addCount
=
0
;
if
(
thisCase
.
caseTime
==
null
||
thisCase
.
finalTime
==
null
||
thisCase
.
space
==
null
||
thisCase
.
space
.
spaceRate
==
null
){
return
new_addCount
;
}
Calendar
caseCalendar
=
Calendar
.
getInstance
();
caseCalendar
.
setTime
(
thisCase
.
caseTime
);
caseCalendar
.
set
(
Calendar
.
SECOND
,
0
);
Calendar
finalCalendar
=
Calendar
.
getInstance
();
finalCalendar
.
setTime
(
thisCase
.
finalTime
);
finalCalendar
.
set
(
Calendar
.
SECOND
,
0
);
do
{
//利用時間差算出累加次數
caseCalendar
.
add
(
Calendar
.
MINUTE
,
(
int
)
(
thisCase
.
space
.
spaceRate
.
perHours
*
60
));
new_addCount
+=
1
;
}
while
(
caseCalendar
.
before
(
finalCalendar
));
return
new_addCount
;
}
public
void
updateCaseDate
(){
Case
tempCase
=
currentCase
.
getValue
();
tempCase
.
caseTime
=
Calendar
.
getInstance
().
getTime
();
...
...
@@ -79,18 +121,126 @@ public class T02StartViewModel extends AndroidViewModel {
}
public
void
initCurrentCase
(){
// 清空佔存
tempCasePhoto
.
clear
();
currentCase
.
setValue
(
newCase
());
}
private
Case
newCase
(){
Case
newCase
=
new
Case
();
newCase
.
caseStatus
=
CaseStatus
.
NEW
;
newCase
.
user
=
currentUser
.
getValue
();
newCase
.
caseTime
=
Calendar
.
getInstance
().
getTime
();
newCase
.
finalTime
=
Calendar
.
getInstance
().
getTime
();
generateBillingNumber
(
newCase
);
return
newCase
;
}
public
void
saveCurrentCase
(){
// TODO: 2022/7/29 case資料寫入db
Case
tempCase
=
currentCase
.
getValue
();
switch
(
tempCase
.
caseStatus
){
case
NEW:
infoRepository
.
executorService
.
execute
(()
->
{
infoRepository
.
caseDao
.
insertAll
(
tempCase
);
for
(
int
i
=
0
;
i
<
tempCasePhoto
.
size
();
i
++){
infoRepository
.
casePhotoDao
.
insertAll
(
tempCasePhoto
.
get
(
i
));
}
tempCasePhoto
.
clear
();
//存進併檔用文字檔
Common
.
writeTXT
(
getApplication
(),
tempCase
.
datePath
,
tempCase
.
userDateFileName
,
tempCase
.
getDetailString
());
updateIdx
(
tempCase
);
Common
.
writeTXT
(
getApplication
(),
tempCase
.
uploadPath
,
tempCase
.
getUploadFileName
(),
tempCase
.
getDetailString
());
// 跳至新單
currentCase
.
postValue
(
newCase
());
});
break
;
case
LIST:
break
;
case
CHANGED:
break
;
case
LOCK:
break
;
default
:
break
;
}
}
/**
* @param photoFile 拍照回傳檔案
*/
public
void
takeNewPhoto
(
File
photoFile
){
Case
tempCase
=
currentCase
.
getValue
();
// 更新照片數量
tempCase
.
photoCount
+=
1
;
// 取得完整路徑
final
String
path
=
photoFile
.
getAbsolutePath
();
// TODO: 2022/7/29 加入車牌辨識功能
String
newPlateNumber
=
"8050-LZ"
;
CasePhoto
newCasePhoto
=
new
CasePhoto
(
0
,
tempCase
.
billingNumber2
,
path
,
newPlateNumber
);
tempCasePhoto
.
add
(
newCasePhoto
);
// 為圖片壓制浮水印
Thread
ModifyPhotoT
=
new
Thread
(
new
ModifyPhoto
(
path
),
"ModifyPhoto_Thread"
);
ModifyPhotoT
.
start
();
// 重新搜尋檔案
MediaScannerConnection
.
scanFile
(
getApplication
().
getApplicationContext
(),
new
String
[]{
path
},
null
,
null
);
// 更新當前案件
currentCase
.
setValue
(
tempCase
);
}
/**
* 檢查案件資料是否完整
* @return true or fasle
*/
public
boolean
caseDataConfirm
(){
Case
tempCase
=
currentCase
.
getValue
();
// 單號檢查
if
(
tempCase
.
billingNumber2
.
trim
().
isEmpty
()
||
tempCase
.
billingNumber2
.
length
()
!=
11
){
return
false
;
}
// 檢查時間
// 檢查車格
if
(
tempCase
.
space
==
null
||
tempCase
.
space
.
id
.
isEmpty
()
||
tempCase
.
space
.
road
==
null
||
tempCase
.
space
.
road
.
id
.
isEmpty
()){
return
false
;
}
// 檢查車種
if
(
tempCase
.
vehicleType
==
null
||
tempCase
.
vehicleType
.
name
.
trim
().
isEmpty
()){
return
false
;
}
// 檢查車牌
if
(!
Common
.
plateRuleCheck
(
tempCase
.
plateNumber
)){
return
false
;
}
// 檢查照片
if
(
tempCase
.
photoCount
==
0
){
return
false
;
}
return
true
;
}
/**
* 產生單號
* 1.依據日期產生第一段條碼
...
...
@@ -112,7 +262,7 @@ public class T02StartViewModel extends AndroidViewModel {
// 初始化目錄
thisCase
.
datePath
=
Environment
.
getExternalStorageDirectory
()
+
getApplication
().
getString
(
R
.
string
.
sysData_path
)
+
Common
.
getDate
(
caseCalendar
,
false
);
thisCase
.
fileNameBackup
=
"/"
+
thisCase
.
shiftId
;
//[A]早/晚
thisCase
.
fileNameBackup
=
"/"
+
thisCase
.
getShift
()
;
//[A]早/晚
thisCase
.
fileNameBackup
+=
userID
+
"-"
;
//[85]使用者代號 [-]
thisCase
.
fileNameBackup
+=
Common
.
getDate
(
caseCalendar
,
false
);
//[20200114]日期
thisCase
.
userDateFileName
=
thisCase
.
fileNameBackup
+
".txt"
;
//[A][85][-][20200114][.txt]
...
...
@@ -141,8 +291,9 @@ public class T02StartViewModel extends AndroidViewModel {
thisCase
.
billingNumber2
=
BN2
.
toString
();
BN2
.
append
(
Common
.
check
(
thisCase
.
billingNumber1
,
thisCase
.
billingNumber2
));
//2碼檢查碼->[19]
thisCase
.
billingNumber2
=
BN2
.
toString
();
}
// TODO: 2022/7/29 加入與資料庫 billingNumber2 欄位比較是否重複
}
/**
* 取得流水號,用來產生第二段條碼
...
...
@@ -178,4 +329,21 @@ public class T02StartViewModel extends AndroidViewModel {
}
/**
* 案件頁面切換下一頁
*/
public
void
pageDown
()
{
int
casesSize
=
cases
.
size
();
// 判斷是否到底了
if
(
casesSize
>
caseCursor
){
}
}
/**
* 案件頁面切換上一頁
*/
public
void
pageUp
()
{
}
}
app/src/main/res/layout/activity_t02_start.xml
View file @
2c215f50
...
...
@@ -398,7 +398,7 @@ tools:layout_editor_absoluteY="25dp">
android:layout_weight=
"0.53"
android:gravity=
"center"
android:textSize=
"24sp"
android:text=
"@{String.valueOf(t02StartViewModel.currentCase.
finalTime
)}"
/>
android:text=
"@{String.valueOf(t02StartViewModel.currentCase.
periodHour
)}"
/>
<TextView
android:id=
"@+id/textView3"
...
...
相關文件/占存檔/999
0 → 100644
View file @
2c215f50
2
相關文件/占存檔/99B17V00189.txt
0 → 100644
View file @
2c215f50
A999;99B17V00189;20220817;10:43;A 中山路A;A216 2 1 中山路A;01 自小客;8052-LZ; ; ;0.5;25;Lat:24.1434911 Lon:120.7285887;1;1;
相關文件/占存檔/A999-20220729
0 → 100644
View file @
2c215f50
A999;99B17V00189;20220817;10:43;A 中山路A;A216 2 1 中山路A;01 自小客;8052-LZ; ; ;0.5;25;Lat:24.1434911 Lon:120.7285887;1;1;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment