Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lib_base
Overview
Overview
Details
Activity
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sikang
lib_base
Commits
e371b4b8
Commit
e371b4b8
authored
Apr 24, 2019
by
sikang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
http://47.100.14.92:8929/sikang/lib_base
update script
parents
54aab50c
15de9484
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
232 additions
and
1038 deletions
+232
-1038
script/release_builder.sh
+1
-0
src/main/AndroidManifest.xml
+18
-34
src/main/java/com/common/activity/TakePhotoActivity.java
+14
-8
src/main/java/tech/starwin/mvp/presenter/UploadPresenter.java
+18
-7
src/main/java/tech/starwin/mvp/presenter/UserPresenter.java
+23
-5
src/main/java/tech/starwin/network/tools/BitmapRequestBody.java
+43
-0
src/main/java/tech/starwin/network/tools/MultipartBodyMaker.java
+9
-2
src/main/java/tech/starwin/utils/Base64.java
+0
-975
src/main/java/tech/starwin/utils/BitmapUtils.java
+63
-0
src/main/java/tech/starwin/utils/FileUtils.java
+2
-1
src/main/java/tech/starwin/utils/SPDataProvider.java
+35
-0
src/main/java/tech/starwin/utils/context_utils/PermissionsHelper.java
+6
-6
No files found.
script/release_builder.sh
View file @
e371b4b8
...
@@ -62,5 +62,6 @@ else
...
@@ -62,5 +62,6 @@ else
echo
"未知的打包方式"
echo
"未知的打包方式"
fi
fi
gradlew clean
cd
lib_base/script/garble/
cd
lib_base/script/garble/
./reset_name.sh
./reset_name.sh
src/main/AndroidManifest.xml
View file @
e371b4b8
...
@@ -3,9 +3,14 @@
...
@@ -3,9 +3,14 @@
package=
"tech.starwin"
>
package=
"tech.starwin"
>
<!--写入SD卡-->
<!--写入SD卡-->
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
tools:node=
"remove"
/>
<!--读取SD卡-->
<!--读取SD卡-->
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
/>
<uses-permission
android:name=
"android.permission.READ_EXTERNAL_STORAGE"
tools:node=
"remove"
/>
<uses-permission
android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
<!--相机-->
<!--相机-->
<uses-permission
android:name=
"android.permission.CAMERA"
/>
<uses-permission
android:name=
"android.permission.CAMERA"
/>
<!--读取联系人信息-->
<!--读取联系人信息-->
...
@@ -75,65 +80,44 @@
...
@@ -75,65 +80,44 @@
android:name=
"com.facebook.accountkit.ClientToken"
android:name=
"com.facebook.accountkit.ClientToken"
android:value=
"@string/ACCOUNT_KIT_CLIENT_TOKEN"
/>
android:value=
"@string/ACCOUNT_KIT_CLIENT_TOKEN"
/>
<activity
<activity
android:name=
"com.facebook.accountkit.ui.AccountKitActivity"
/>
android:name=
"com.facebook.accountkit.ui.AccountKitActivity"
/>
<!--地区选择-->
<!--地区选择-->
<activity
<activity
android:name=
"com.common.activity.RegionActivity"
/>
android:name=
"com.common.activity.RegionActivity"
/>
<!-- Zendesk -->
<!-- Zendesk -->
<activity
<activity
android:name=
"com.common.activity.RefreshDeskActivity"
android:name=
"com.common.activity.RefreshDeskActivity"
android:windowSoftInputMode=
"adjustResize"
/>
android:windowSoftInputMode=
"adjustResize"
/>
<activity
<activity
android:name=
"com.common.activity.RefreshDeskListActivity"
/>
android:name=
"com.common.activity.RefreshDeskListActivity"
/>
<!--拍照-->
<!--拍照-->
<activity
<activity
android:name=
"com.common.activity.TakePhotoActivity"
/>
android:name=
"com.common.activity.TakePhotoActivity"
/>
<!--还款指南-->
<!--还款指南-->
<activity
<activity
android:name=
"com.common.activity.RepaymentGuideActivity"
/>
android:name=
"com.common.activity.RepaymentGuideActivity"
/>
<!--Web-->
<!--Web-->
<activity
<activity
android:name=
"com.common.activity.WebActivity"
/>
android:name=
"com.common.activity.WebActivity"
/>
<!--注册协议和隐私政策-->
<!--注册协议和隐私政策-->
<activity
<activity
android:name=
"com.common.activity.AgreementPolicyActivity"
android:name=
"com.common.activity.AgreementPolicyActivity"
android:launchMode=
"standard"
android:launchMode=
"standard"
/>
/>
<!--帮助中心-->
<!--帮助中心-->
<activity
<activity
android:name=
"com.common.activity.HelpCenterActivity"
/>
android:name=
"com.common.activity.HelpCenterActivity"
/>
<!--关于我们-->
<!--关于我们-->
<activity
<activity
android:name=
"com.common.activity.AboutUsActivity"
/>
android:name=
"com.common.activity.AboutUsActivity"
/>
<!--活动中心-->
<!--活动中心-->
<activity
<activity
android:name=
"com.common.activity.ActivityCenter"
/>
android:name=
"com.common.activity.ActivityCenter"
/>
<!--活动中心-->
<!--活动中心-->
<activity
<activity
android:name=
"com.common.activity.MessageListActivity"
/>
android:name=
"com.common.activity.MessageListActivity"
/>
<!--<receiver-->
<!--<receiver-->
<!--tools:node="remove"-->
<!--tools:node="remove"-->
...
...
src/main/java/com/common/activity/TakePhotoActivity.java
View file @
e371b4b8
...
@@ -12,6 +12,7 @@ import android.widget.ImageView;
...
@@ -12,6 +12,7 @@ import android.widget.ImageView;
import
com.qmuiteam.qmui.util.QMUIStatusBarHelper
;
import
com.qmuiteam.qmui.util.QMUIStatusBarHelper
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
tech.starwin.R
;
import
tech.starwin.R
;
...
@@ -20,6 +21,8 @@ import com.common.base.BaseActivity;
...
@@ -20,6 +21,8 @@ import com.common.base.BaseActivity;
import
tech.starwin.impl.OnNoShakeClickListener
;
import
tech.starwin.impl.OnNoShakeClickListener
;
import
tech.starwin.utils.BitmapUtils
;
import
tech.starwin.utils.BitmapUtils
;
import
tech.starwin.utils.FileUtils
;
import
tech.starwin.utils.FileUtils
;
import
tech.starwin.utils.PreferencesManager
;
import
tech.starwin.utils.SPDataProvider
;
import
tech.starwin.utils.context_utils.ActivityJumper
;
import
tech.starwin.utils.context_utils.ActivityJumper
;
import
tech.starwin.utils.context_utils.EasyActivityResult
;
import
tech.starwin.utils.context_utils.EasyActivityResult
;
import
tech.starwin.utils.ui_utils.QMUIHelper
;
import
tech.starwin.utils.ui_utils.QMUIHelper
;
...
@@ -100,6 +103,17 @@ public class TakePhotoActivity extends BaseActivity {
...
@@ -100,6 +103,17 @@ public class TakePhotoActivity extends BaseActivity {
public
void
onEventClick
(
View
v
)
{
public
void
onEventClick
(
View
v
)
{
if
(
v
.
getId
()
==
R
.
id
.
button_shoot
)
{
if
(
v
.
getId
()
==
R
.
id
.
button_shoot
)
{
cameraView
.
captureImage
(
bitmap
->
{
cameraView
.
captureImage
(
bitmap
->
{
// long pix_size = bitmap.getWidth() * bitmap.getHeight();
// float scale = 720 * 1080 / (float) pix_size;
// BitmapUtils.scaleBitmap(bitmap, scale);
// if(TextUtils.equals(type, PhotoType.KTP.name())){
// SPDataProvider.saveKTPImage(bitmap);
// }else if(TextUtils.equals(type, PhotoType.WORK_CARD.name())){
// SPDataProvider.saveWorkImage(bitmap);
// }
// setResult(RESULT_OK);
// finish();
File
image
=
FileUtils
.
getImageFile
(
getApplicationContext
(),
KTP_IMAGE
);
File
image
=
FileUtils
.
getImageFile
(
getApplicationContext
(),
KTP_IMAGE
);
if
(!
image
.
exists
())
{
if
(!
image
.
exists
())
{
image
.
mkdir
();
image
.
mkdir
();
...
@@ -124,14 +138,6 @@ public class TakePhotoActivity extends BaseActivity {
...
@@ -124,14 +138,6 @@ public class TakePhotoActivity extends BaseActivity {
setResult
(
RESULT_OK
,
intent
);
setResult
(
RESULT_OK
,
intent
);
finish
();
finish
();
// try {
// FileOutputStream outputStream = new FileOutputStream(image.getPath());
// outputStream.write(data);
// outputStream.close();
//
// } catch (java.io.IOException e) {
// e.printStackTrace();
// }
});
});
}
else
if
(
v
.
getId
()
==
R
.
id
.
button_cancel
)
{
}
else
if
(
v
.
getId
()
==
R
.
id
.
button_cancel
)
{
setResult
(
RESULT_CANCELED
);
setResult
(
RESULT_CANCELED
);
...
...
src/main/java/tech/starwin/mvp/presenter/UploadPresenter.java
View file @
e371b4b8
package
tech
.
starwin
.
mvp
.
presenter
;
package
tech
.
starwin
.
mvp
.
presenter
;
import
android.content.Context
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.NonNull
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
...
@@ -13,11 +14,8 @@ import java.util.List;
...
@@ -13,11 +14,8 @@ import java.util.List;
import
io.reactivex.Observable
;
import
io.reactivex.Observable
;
import
io.reactivex.ObservableSource
;
import
io.reactivex.ObservableSource
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.functions.Consumer
;
import
io.reactivex.functions.Function
;
import
io.reactivex.functions.Function
;
import
io.reactivex.functions.Predicate
;
import
okhttp3.MultipartBody
;
import
io.reactivex.schedulers.Schedulers
;
import
tech.starwin.LibConfig
;
import
tech.starwin.LibConfig
;
import
tech.starwin.base.BasePresenter
;
import
tech.starwin.base.BasePresenter
;
import
tech.starwin.constants.TrackEvent
;
import
tech.starwin.constants.TrackEvent
;
...
@@ -28,9 +26,8 @@ import com.common.bean.BasicAck;
...
@@ -28,9 +26,8 @@ import com.common.bean.BasicAck;
import
com.common.bean.OcrResultBean
;
import
com.common.bean.OcrResultBean
;
import
com.google.gson.JsonObject
;
import
com.google.gson.JsonObject
;
import
tech.starwin.utils.LogUtils
;
import
tech.starwin.utils.LoginManager
;
import
tech.starwin.utils.LoginManager
;
import
tech.starwin.
uti
ls.MultipartBodyMaker
;
import
tech.starwin.
network.too
ls.MultipartBodyMaker
;
import
tech.starwin.utils.PreferencesManager
;
import
tech.starwin.utils.PreferencesManager
;
import
tech.starwin.utils.TrackEventHelper
;
import
tech.starwin.utils.TrackEventHelper
;
import
tech.starwin.utils.context_utils.AppInfoUtils
;
import
tech.starwin.utils.context_utils.AppInfoUtils
;
...
@@ -48,7 +45,21 @@ public class UploadPresenter extends BasePresenter<UploadApi> {
...
@@ -48,7 +45,21 @@ public class UploadPresenter extends BasePresenter<UploadApi> {
* 身份证ocr识别
* 身份证ocr识别
*/
*/
public
void
identityOcr
(
final
String
action
,
@NonNull
File
file
)
{
public
void
identityOcr
(
final
String
action
,
@NonNull
File
file
)
{
handleRequest
(
apiService
.
identityOcr
(
MultipartBodyMaker
.
makeSimplePart
(
"file"
,
file
),
LoginManager
.
get
().
getToken
()),
identityOcr
(
action
,
MultipartBodyMaker
.
makeSimplePart
(
"file"
,
file
));
}
/**
* 身份证ocr识别
*/
public
void
identityOcr
(
final
String
action
,
@NonNull
Bitmap
bitmap
)
{
identityOcr
(
action
,
MultipartBodyMaker
.
makeSimplePart
(
"file"
,
"ktp_img"
,
bitmap
,
Bitmap
.
CompressFormat
.
JPEG
));
}
/**
* 身份证ocr识别,直接使用Bitmap
*/
private
void
identityOcr
(
final
String
action
,
MultipartBody
.
Part
filePart
)
{
handleRequest
(
apiService
.
identityOcr
(
filePart
,
LoginManager
.
get
().
getToken
()),
new
HttpObserver
<
OcrResultBean
>()
{
new
HttpObserver
<
OcrResultBean
>()
{
@Override
@Override
public
void
onStart
()
{
public
void
onStart
()
{
...
...
src/main/java/tech/starwin/mvp/presenter/UserPresenter.java
View file @
e371b4b8
...
@@ -2,6 +2,7 @@ package tech.starwin.mvp.presenter;
...
@@ -2,6 +2,7 @@ package tech.starwin.mvp.presenter;
import
android.annotation.SuppressLint
;
import
android.annotation.SuppressLint
;
import
android.graphics.Bitmap
;
import
android.text.TextUtils
;
import
android.text.TextUtils
;
import
org.greenrobot.eventbus.EventBus
;
import
org.greenrobot.eventbus.EventBus
;
...
@@ -17,6 +18,7 @@ import io.reactivex.functions.Function;
...
@@ -17,6 +18,7 @@ import io.reactivex.functions.Function;
import
io.reactivex.functions.Function4
;
import
io.reactivex.functions.Function4
;
import
io.reactivex.functions.Predicate
;
import
io.reactivex.functions.Predicate
;
import
io.reactivex.schedulers.Schedulers
;
import
io.reactivex.schedulers.Schedulers
;
import
okhttp3.MultipartBody
;
import
okhttp3.ResponseBody
;
import
okhttp3.ResponseBody
;
import
tech.starwin.base.BasePresenter
;
import
tech.starwin.base.BasePresenter
;
import
tech.starwin.constants.ActionEnum
;
import
tech.starwin.constants.ActionEnum
;
...
@@ -44,7 +46,7 @@ import com.common.bean.UserBean;
...
@@ -44,7 +46,7 @@ import com.common.bean.UserBean;
import
tech.starwin.network.Gateway
;
import
tech.starwin.network.Gateway
;
import
tech.starwin.network.ServiceGenerator
;
import
tech.starwin.network.ServiceGenerator
;
import
tech.starwin.utils.LoginManager
;
import
tech.starwin.utils.LoginManager
;
import
tech.starwin.
uti
ls.MultipartBodyMaker
;
import
tech.starwin.
network.too
ls.MultipartBodyMaker
;
import
tech.starwin.utils.PreferencesManager
;
import
tech.starwin.utils.PreferencesManager
;
import
tech.starwin.utils.TrackEventHelper
;
import
tech.starwin.utils.TrackEventHelper
;
...
@@ -472,10 +474,26 @@ public class UserPresenter extends BasePresenter<UserApi> {
...
@@ -472,10 +474,26 @@ public class UserPresenter extends BasePresenter<UserApi> {
}
}
public
void
submitEmploymentInfo
(
String
action
,
File
workCardImage
,
EmploymentServerBean
employmentBean
)
{
MultipartBody
.
Part
part
=
null
;
if
(
workCardImage
!=
null
&&
workCardImage
.
exists
())
{
part
=
MultipartBodyMaker
.
makeSimplePart
(
"file"
,
workCardImage
);
}
submitEmploymentInfo
(
action
,
part
,
employmentBean
);
}
// public void submitEmploymentInfo(String action, Bitmap bitmap, EmploymentServerBean employmentBean) {
// MultipartBody.Part part = null;
// if (bitmap != null) {
// part = MultipartBodyMaker.makeSimplePart("file", "word_card", bitmap, Bitmap.CompressFormat.JPEG);
// }
// submitEmploymentInfo(action, part, employmentBean);
// }
/**
/**
* 提交工作信息
* 提交工作信息
*/
*/
p
ublic
void
submitEmploymentInfo
(
String
action
,
File
workCardImage
,
EmploymentServerBean
employmentBean
)
{
p
rivate
void
submitEmploymentInfo
(
String
action
,
MultipartBody
.
Part
part
,
EmploymentServerBean
employmentBean
)
{
Observable
<
ResponseBody
>
info
=
ServiceGenerator
.
getService
(
UserApi
.
class
)
Observable
<
ResponseBody
>
info
=
ServiceGenerator
.
getService
(
UserApi
.
class
)
.
submitEmploymentInfo
(
employmentBean
.
getCompanyName
(),
.
submitEmploymentInfo
(
employmentBean
.
getCompanyName
(),
employmentBean
.
getCompanyProvince
(),
employmentBean
.
getCompanyProvince
(),
...
@@ -488,8 +506,8 @@ public class UserPresenter extends BasePresenter<UserApi> {
...
@@ -488,8 +506,8 @@ public class UserPresenter extends BasePresenter<UserApi> {
employmentBean
.
getSalary
(),
employmentBean
.
getSalary
(),
LoginManager
.
get
().
getToken
());
LoginManager
.
get
().
getToken
());
if
(
workCardImage
!=
null
&&
workCardImage
.
exists
()
)
{
if
(
part
!=
null
)
{
Observable
<
ResponseBody
>
upload
=
getService
(
UploadApi
.
class
).
uploadPhoto
(
MultipartBodyMaker
.
makeSimplePart
(
"file"
,
workCardImage
)
,
"EMPLOYMENT_PHOTO"
,
LoginManager
.
get
().
getToken
());
Observable
<
ResponseBody
>
upload
=
getService
(
UploadApi
.
class
).
uploadPhoto
(
part
,
"EMPLOYMENT_PHOTO"
,
LoginManager
.
get
().
getToken
());
handleRequest
(
action
,
Observable
.
zip
(
info
,
upload
,
new
BiFunction
<
ResponseBody
,
ResponseBody
,
Boolean
>()
{
handleRequest
(
action
,
Observable
.
zip
(
info
,
upload
,
new
BiFunction
<
ResponseBody
,
ResponseBody
,
Boolean
>()
{
@Override
@Override
...
@@ -579,7 +597,7 @@ public class UserPresenter extends BasePresenter<UserApi> {
...
@@ -579,7 +597,7 @@ public class UserPresenter extends BasePresenter<UserApi> {
/**
/**
* 获取其他照片
* 获取其他照片
*
*
/
*/
public
void
getPhotoList
(
String
action
)
{
public
void
getPhotoList
(
String
action
)
{
handleRequest
(
action
,
apiService
.
getPhotoList
());
handleRequest
(
action
,
apiService
.
getPhotoList
());
}
}
...
...
src/main/java/tech/starwin/network/tools/BitmapRequestBody.java
0 → 100644
View file @
e371b4b8
package
tech
.
starwin
.
network
.
tools
;
import
android.graphics.Bitmap
;
import
java.io.IOException
;
import
javax.annotation.Nullable
;
import
okhttp3.MediaType
;
import
okhttp3.RequestBody
;
import
okio.BufferedSink
;
/**
* Created by SiKang on 2019/4/22.
*/
public
class
BitmapRequestBody
extends
RequestBody
{
private
Bitmap
bitmap
;
private
Bitmap
.
CompressFormat
format
;
public
BitmapRequestBody
(
Bitmap
bitmap
,
Bitmap
.
CompressFormat
format
)
{
this
.
bitmap
=
bitmap
;
this
.
format
=
format
;
}
@Nullable
@Override
public
MediaType
contentType
()
{
if
(
format
==
Bitmap
.
CompressFormat
.
JPEG
)
{
return
MediaType
.
parse
(
"image/jpeg"
);
}
else
if
(
format
==
Bitmap
.
CompressFormat
.
PNG
)
{
return
MediaType
.
parse
(
"image/png"
);
}
else
if
(
format
==
Bitmap
.
CompressFormat
.
WEBP
)
{
return
MediaType
.
parse
(
"image/webp"
);
}
return
null
;
}
@Override
public
void
writeTo
(
BufferedSink
sink
)
throws
IOException
{
bitmap
.
compress
(
format
,
100
,
sink
.
outputStream
());
}
}
src/main/java/tech/starwin/
uti
ls/MultipartBodyMaker.java
→
src/main/java/tech/starwin/
network/too
ls/MultipartBodyMaker.java
View file @
e371b4b8
package
tech
.
starwin
.
utils
;
package
tech
.
starwin
.
network
.
tools
;
import
android.graphics.Bitmap
;
import
java.io.File
;
import
java.io.File
;
import
java.util.List
;
import
java.util.List
;
...
@@ -6,6 +8,7 @@ import java.util.List;
...
@@ -6,6 +8,7 @@ import java.util.List;
import
okhttp3.MediaType
;
import
okhttp3.MediaType
;
import
okhttp3.MultipartBody
;
import
okhttp3.MultipartBody
;
import
okhttp3.RequestBody
;
import
okhttp3.RequestBody
;
import
tech.starwin.utils.FileUtils
;
/**
/**
* Created by SiKang on 2018/9/28.
* Created by SiKang on 2018/9/28.
...
@@ -35,6 +38,11 @@ public class MultipartBodyMaker {
...
@@ -35,6 +38,11 @@ public class MultipartBodyMaker {
return
MultipartBody
.
Part
.
createFormData
(
name
,
file
.
getName
(),
requestFile
);
return
MultipartBody
.
Part
.
createFormData
(
name
,
file
.
getName
(),
requestFile
);
}
}
public
static
MultipartBody
.
Part
makeSimplePart
(
String
name
,
String
fileName
,
Bitmap
bitmap
,
Bitmap
.
CompressFormat
format
)
{
RequestBody
requestFile
=
new
BitmapRequestBody
(
bitmap
,
format
);
return
MultipartBody
.
Part
.
createFormData
(
name
,
fileName
,
requestFile
);
}
public
static
MultipartBody
.
Part
makeSimplePart
(
String
name
,
String
value
)
{
public
static
MultipartBody
.
Part
makeSimplePart
(
String
name
,
String
value
)
{
return
MultipartBody
.
Part
.
createFormData
(
name
,
value
);
return
MultipartBody
.
Part
.
createFormData
(
name
,
value
);
}
}
...
@@ -78,6 +86,5 @@ public class MultipartBodyMaker {
...
@@ -78,6 +86,5 @@ public class MultipartBodyMaker {
public
MultipartBodyMaker
build
()
{
public
MultipartBodyMaker
build
()
{
return
new
MultipartBodyMaker
(
builder
);
return
new
MultipartBodyMaker
(
builder
);
}
}
}
}
}
}
src/main/java/tech/starwin/utils/Base64.java
deleted
100644 → 0
View file @
54aab50c
package
tech
.
starwin
.
utils
;
import
java.io.FilterOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.nio.ByteBuffer
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Arrays
;
import
java.util.Objects
;
/**
* This class consists exclusively of static methods for obtaining
* encoders and decoders for the Base64 encoding scheme. The
* implementation of this class supports the following types of Base64
* as specified in
* <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a> and
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
*
* <ul>
* <li><a name="basic"><b>Basic</b></a>
* <p> Uses "The Base64 Alphabet" as specified in Table 1 of
* RFC 4648 and RFC 2045 for encoding and decoding operation.
* The encoder does not add any line feed (line separator)
* character. The decoder rejects data that contains characters
* outside the base64 alphabet.</p></li>
*
* <li><a name="url"><b>URL and Filename safe</b></a>
* <p> Uses the "URL and Filename safe Base64 Alphabet" as specified
* in Table 2 of RFC 4648 for encoding and decoding. The
* encoder does not add any line feed (line separator) character.
* The decoder rejects data that contains characters outside the
* base64 alphabet.</p></li>
*
* <li><a name="mime"><b>MIME</b></a>
* <p> Uses the "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by
* a linefeed {@code '\n'} as the line separator. No line separator
* is added to the end of the encoded output. All line separators
* or other characters not found in the base64 alphabet table are
* ignored in decoding operation.</p></li>
* </ul>
*
* <p> Unless otherwise noted, passing a {@code null} argument to a
* method of this class will cause a {@link java.lang.NullPointerException
* NullPointerException} to be thrown.
*
* @author Xueming Shen
* @since 1.8
*/
public
class
Base64
{
private
Base64
()
{}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
*
* @return A Base64 encoder.
*/
public
static
Encoder
getEncoder
()
{
return
Encoder
.
RFC4648
;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#url">URL and Filename safe</a> type base64
* encoding scheme.
*
* @return A Base64 encoder.
*/
public
static
Encoder
getUrlEncoder
()
{
return
Encoder
.
RFC4648_URLSAFE
;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#mime">MIME</a> type base64 encoding scheme.
*
* @return A Base64 encoder.
*/
public
static
Encoder
getMimeEncoder
()
{
return
Encoder
.
RFC2045
;
}
/**
* Returns a {@link Encoder} that encodes using the
* <a href="#mime">MIME</a> type base64 encoding scheme
* with specified line length and line separators.
*
* @param lineLength
* the length of each output line (rounded down to nearest multiple
* of 4). If {@code lineLength <= 0} the output will not be separated
* in lines
* @param lineSeparator
* the line separator for each output line
*
* @return A Base64 encoder.
*
* @throws IllegalArgumentException if {@code lineSeparator} includes any
* character of "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045.
*/
public
static
Encoder
getMimeEncoder
(
int
lineLength
,
byte
[]
lineSeparator
)
{
Objects
.
requireNonNull
(
lineSeparator
);
int
[]
base64
=
Decoder
.
fromBase64
;
for
(
byte
b
:
lineSeparator
)
{
if
(
base64
[
b
&
0xff
]
!=
-
1
)
throw
new
IllegalArgumentException
(
"Illegal base64 line separator character 0x"
+
Integer
.
toString
(
b
,
16
));
}
if
(
lineLength
<=
0
)
{
return
Encoder
.
RFC4648
;
}
return
new
Encoder
(
false
,
lineSeparator
,
lineLength
>>
2
<<
2
,
true
);
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#basic">Basic</a> type base64 encoding scheme.
*
* @return A Base64 decoder.
*/
public
static
Decoder
getDecoder
()
{
return
Decoder
.
RFC4648
;
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#url">URL and Filename safe</a> type base64
* encoding scheme.
*
* @return A Base64 decoder.
*/
public
static
Decoder
getUrlDecoder
()
{
return
Decoder
.
RFC4648_URLSAFE
;
}
/**
* Returns a {@link Decoder} that decodes using the
* <a href="#mime">MIME</a> type base64 decoding scheme.
*
* @return A Base64 decoder.
*/
public
static
Decoder
getMimeDecoder
()
{
return
Decoder
.
RFC2045
;
}
/**
* This class implements an encoder for encoding byte data using
* the Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
*
* <p> Instances of {@link Encoder} class are safe for use by
* multiple concurrent threads.
*
* <p> Unless otherwise noted, passing a {@code null} argument to
* a method of this class will cause a
* {@link java.lang.NullPointerException NullPointerException} to
* be thrown.
*
* @see Decoder
* @since 1.8
*/
public
static
class
Encoder
{
private
final
byte
[]
newline
;
private
final
int
linemax
;
private
final
boolean
isURL
;
private
final
boolean
doPadding
;
private
Encoder
(
boolean
isURL
,
byte
[]
newline
,
int
linemax
,
boolean
doPadding
)
{
this
.
isURL
=
isURL
;
this
.
newline
=
newline
;
this
.
linemax
=
linemax
;
this
.
doPadding
=
doPadding
;
}
/**
* This array is a lookup table that translates 6-bit positive integer
* index values into their "Base64 Alphabet" equivalents as specified
* in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648).
*/
private
static
final
char
[]
toBase64
=
{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
,
'G'
,
'H'
,
'I'
,
'J'
,
'K'
,
'L'
,
'M'
,
'N'
,
'O'
,
'P'
,
'Q'
,
'R'
,
'S'
,
'T'
,
'U'
,
'V'
,
'W'
,
'X'
,
'Y'
,
'Z'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
'l'
,
'm'
,
'n'
,
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
'w'
,
'x'
,
'y'
,
'z'
,
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'+'
,
'/'
};
/**
* It's the lookup table for "URL and Filename safe Base64" as specified
* in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and
* '_'. This table is used when BASE64_URL is specified.
*/
private
static
final
char
[]
toBase64URL
=
{
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
,
'G'
,
'H'
,
'I'
,
'J'
,
'K'
,
'L'
,
'M'
,
'N'
,
'O'
,
'P'
,
'Q'
,
'R'
,
'S'
,
'T'
,
'U'
,
'V'
,
'W'
,
'X'
,
'Y'
,
'Z'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'g'
,
'h'
,
'i'
,
'j'
,
'k'
,
'l'
,
'm'
,
'n'
,
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
,
'u'
,
'v'
,
'w'
,
'x'
,
'y'
,
'z'
,
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'-'
,
'_'
};
private
static
final
int
MIMELINEMAX
=
76
;
private
static
final
byte
[]
CRLF
=
new
byte
[]
{
'\r'
,
'\n'
};
static
final
Encoder
RFC4648
=
new
Encoder
(
false
,
null
,
-
1
,
true
);
static
final
Encoder
RFC4648_URLSAFE
=
new
Encoder
(
true
,
null
,
-
1
,
true
);
static
final
Encoder
RFC2045
=
new
Encoder
(
false
,
CRLF
,
MIMELINEMAX
,
true
);
private
final
int
outLength
(
int
srclen
)
{
int
len
=
0
;
if
(
doPadding
)
{
len
=
4
*
((
srclen
+
2
)
/
3
);
}
else
{
int
n
=
srclen
%
3
;
len
=
4
*
(
srclen
/
3
)
+
(
n
==
0
?
0
:
n
+
1
);
}
if
(
linemax
>
0
)
// line separators
len
+=
(
len
-
1
)
/
linemax
*
newline
.
length
;
return
len
;
}
/**
* Encodes all bytes from the specified byte array into a newly-allocated
* byte array using the {@link Base64} encoding scheme. The returned byte
* array is of the length of the resulting bytes.
*
* @param src
* the byte array to encode
* @return A newly-allocated byte array containing the resulting
* encoded bytes.
*/
public
byte
[]
encode
(
byte
[]
src
)
{
int
len
=
outLength
(
src
.
length
);
// dst array size
byte
[]
dst
=
new
byte
[
len
];
int
ret
=
encode0
(
src
,
0
,
src
.
length
,
dst
);
if
(
ret
!=
dst
.
length
)
return
Arrays
.
copyOf
(
dst
,
ret
);
return
dst
;
}
/**
* Encodes all bytes from the specified byte array using the
* {@link Base64} encoding scheme, writing the resulting bytes to the
* given output byte array, starting at offset 0.
*
* <p> It is the responsibility of the invoker of this method to make
* sure the output byte array {@code dst} has enough space for encoding
* all bytes from the input byte array. No bytes will be written to the
* output byte array if the output byte array is not big enough.
*
* @param src
* the byte array to encode
* @param dst
* the output byte array
* @return The number of bytes written to the output byte array
*
* @throws IllegalArgumentException if {@code dst} does not have enough
* space for encoding all input bytes.
*/
public
int
encode
(
byte
[]
src
,
byte
[]
dst
)
{
int
len
=
outLength
(
src
.
length
);
// dst array size
if
(
dst
.
length
<
len
)
throw
new
IllegalArgumentException
(
"Output byte array is too small for encoding all input bytes"
);
return
encode0
(
src
,
0
,
src
.
length
,
dst
);
}
/**
* Encodes the specified byte array into a String using the {@link Base64}
* encoding scheme.
*
* <p> This method first encodes all input bytes into a base64 encoded
* byte array and then constructs a new String by using the encoded byte
* array and the {@link java.nio.charset.StandardCharsets#ISO_8859_1
* ISO-8859-1} charset.
*
* <p> In other words, an invocation of this method has exactly the same
* effect as invoking
* {@code new String(encode(src), StandardCharsets.ISO_8859_1)}.
*
* @param src
* the byte array to encode
* @return A String containing the resulting Base64 encoded characters
*/
@SuppressWarnings
(
"deprecation"
)
public
String
encodeToString
(
byte
[]
src
)
{
byte
[]
encoded
=
encode
(
src
);
return
new
String
(
encoded
,
0
,
0
,
encoded
.
length
);
}
/**
* Encodes all remaining bytes from the specified byte buffer into
* a newly-allocated ByteBuffer using the {@link Base64} encoding
* scheme.
*
* Upon return, the source buffer's position will be updated to
* its limit; its limit will not have been changed. The returned
* output buffer's position will be zero and its limit will be the
* number of resulting encoded bytes.
*
* @param buffer
* the source ByteBuffer to encode
* @return A newly-allocated byte buffer containing the encoded bytes.
*/
public
ByteBuffer
encode
(
ByteBuffer
buffer
)
{
int
len
=
outLength
(
buffer
.
remaining
());
byte
[]
dst
=
new
byte
[
len
];
int
ret
=
0
;
if
(
buffer
.
hasArray
())
{
ret
=
encode0
(
buffer
.
array
(),
buffer
.
arrayOffset
()
+
buffer
.
position
(),
buffer
.
arrayOffset
()
+
buffer
.
limit
(),
dst
);
buffer
.
position
(
buffer
.
limit
());
}
else
{
byte
[]
src
=
new
byte
[
buffer
.
remaining
()];
buffer
.
get
(
src
);
ret
=
encode0
(
src
,
0
,
src
.
length
,
dst
);
}
if
(
ret
!=
dst
.
length
)
dst
=
Arrays
.
copyOf
(
dst
,
ret
);
return
ByteBuffer
.
wrap
(
dst
);
}
/**
* Wraps an output stream for encoding byte data using the {@link Base64}
* encoding scheme.
*
* <p> It is recommended to promptly close the returned output stream after
* use, during which it will flush all possible leftover bytes to the underlying
* output stream. Closing the returned output stream will close the underlying
* output stream.
*
* @param os
* the output stream.
* @return the output stream for encoding the byte data into the
* specified Base64 encoded format
*/
public
OutputStream
wrap
(
OutputStream
os
)
{
Objects
.
requireNonNull
(
os
);
return
new
EncOutputStream
(
os
,
isURL
?
toBase64URL
:
toBase64
,
newline
,
linemax
,
doPadding
);
}
/**
* Returns an encoder instance that encodes equivalently to this one,
* but without adding any padding character at the end of the encoded
* byte data.
*
* <p> The encoding scheme of this encoder instance is unaffected by
* this invocation. The returned encoder instance should be used for
* non-padding encoding operation.
*
* @return an equivalent encoder that encodes without adding any
* padding character at the end
*/
public
Encoder
withoutPadding
()
{
if
(!
doPadding
)
return
this
;
return
new
Encoder
(
isURL
,
newline
,
linemax
,
false
);
}
private
int
encode0
(
byte
[]
src
,
int
off
,
int
end
,
byte
[]
dst
)
{
char
[]
base64
=
isURL
?
toBase64URL
:
toBase64
;
int
sp
=
off
;
int
slen
=
(
end
-
off
)
/
3
*
3
;
int
sl
=
off
+
slen
;
if
(
linemax
>
0
&&
slen
>
linemax
/
4
*
3
)
slen
=
linemax
/
4
*
3
;
int
dp
=
0
;
while
(
sp
<
sl
)
{
int
sl0
=
Math
.
min
(
sp
+
slen
,
sl
);
for
(
int
sp0
=
sp
,
dp0
=
dp
;
sp0
<
sl0
;
)
{
int
bits
=
(
src
[
sp0
++]
&
0xff
)
<<
16
|
(
src
[
sp0
++]
&
0xff
)
<<
8
|
(
src
[
sp0
++]
&
0xff
);
dst
[
dp0
++]
=
(
byte
)
base64
[(
bits
>>>
18
)
&
0x3f
];
dst
[
dp0
++]
=
(
byte
)
base64
[(
bits
>>>
12
)
&
0x3f
];
dst
[
dp0
++]
=
(
byte
)
base64
[(
bits
>>>
6
)
&
0x3f
];
dst
[
dp0
++]
=
(
byte
)
base64
[
bits
&
0x3f
];
}
int
dlen
=
(
sl0
-
sp
)
/
3
*
4
;
dp
+=
dlen
;
sp
=
sl0
;
if
(
dlen
==
linemax
&&
sp
<
end
)
{
for
(
byte
b
:
newline
){
dst
[
dp
++]
=
b
;
}
}
}
if
(
sp
<
end
)
{
// 1 or 2 leftover bytes
int
b0
=
src
[
sp
++]
&
0xff
;
dst
[
dp
++]
=
(
byte
)
base64
[
b0
>>
2
];
if
(
sp
==
end
)
{
dst
[
dp
++]
=
(
byte
)
base64
[(
b0
<<
4
)
&
0x3f
];
if
(
doPadding
)
{
dst
[
dp
++]
=
'='
;
dst
[
dp
++]
=
'='
;
}
}
else
{
int
b1
=
src
[
sp
++]
&
0xff
;
dst
[
dp
++]
=
(
byte
)
base64
[(
b0
<<
4
)
&
0x3f
|
(
b1
>>
4
)];
dst
[
dp
++]
=
(
byte
)
base64
[(
b1
<<
2
)
&
0x3f
];
if
(
doPadding
)
{
dst
[
dp
++]
=
'='
;
}
}
}
return
dp
;
}
}
/**
* This class implements a decoder for decoding byte data using the
* Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
*
* <p> The Base64 padding character {@code '='} is accepted and
* interpreted as the end of the encoded byte data, but is not
* required. So if the final unit of the encoded byte data only has
* two or three Base64 characters (without the corresponding padding
* character(s) padded), they are decoded as if followed by padding
* character(s). If there is a padding character present in the
* final unit, the correct number of padding character(s) must be
* present, otherwise {@code IllegalArgumentException} (
* {@code IOException} when reading from a Base64 stream) is thrown
* during decoding.
*
* <p> Instances of {@link Decoder} class are safe for use by
* multiple concurrent threads.
*
* <p> Unless otherwise noted, passing a {@code null} argument to
* a method of this class will cause a
* {@link java.lang.NullPointerException NullPointerException} to
* be thrown.
*
* @see Encoder
* @since 1.8
*/
public
static
class
Decoder
{
private
final
boolean
isURL
;
private
final
boolean
isMIME
;
private
Decoder
(
boolean
isURL
,
boolean
isMIME
)
{
this
.
isURL
=
isURL
;
this
.
isMIME
=
isMIME
;
}
/**
* Lookup table for decoding unicode characters drawn from the
* "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into
* their 6-bit positive integer equivalents. Characters that
* are not in the Base64 alphabet but fall within the bounds of
* the array are encoded to -1.
*
*/
private
static
final
int
[]
fromBase64
=
new
int
[
256
];
static
{
Arrays
.
fill
(
fromBase64
,
-
1
);
for
(
int
i
=
0
;
i
<
Encoder
.
toBase64
.
length
;
i
++)
fromBase64
[
Encoder
.
toBase64
[
i
]]
=
i
;
fromBase64
[
'='
]
=
-
2
;
}
/**
* Lookup table for decoding "URL and Filename safe Base64 Alphabet"
* as specified in Table2 of the RFC 4648.
*/
private
static
final
int
[]
fromBase64URL
=
new
int
[
256
];
static
{
Arrays
.
fill
(
fromBase64URL
,
-
1
);
for
(
int
i
=
0
;
i
<
Encoder
.
toBase64URL
.
length
;
i
++)
fromBase64URL
[
Encoder
.
toBase64URL
[
i
]]
=
i
;
fromBase64URL
[
'='
]
=
-
2
;
}
static
final
Decoder
RFC4648
=
new
Decoder
(
false
,
false
);
static
final
Decoder
RFC4648_URLSAFE
=
new
Decoder
(
true
,
false
);
static
final
Decoder
RFC2045
=
new
Decoder
(
false
,
true
);
/**
* Decodes all bytes from the input byte array using the {@link Base64}
* encoding scheme, writing the results into a newly-allocated output
* byte array. The returned byte array is of the length of the resulting
* bytes.
*
* @param src
* the byte array to decode
*
* @return A newly-allocated byte array containing the decoded bytes.
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme
*/
public
byte
[]
decode
(
byte
[]
src
)
{
byte
[]
dst
=
new
byte
[
outLength
(
src
,
0
,
src
.
length
)];
int
ret
=
decode0
(
src
,
0
,
src
.
length
,
dst
);
if
(
ret
!=
dst
.
length
)
{
dst
=
Arrays
.
copyOf
(
dst
,
ret
);
}
return
dst
;
}
/**
* Decodes a Base64 encoded String into a newly-allocated byte array
* using the {@link Base64} encoding scheme.
*
* <p> An invocation of this method has exactly the same effect as invoking
* {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))}
*
* @param src
* the string to decode
*
* @return A newly-allocated byte array containing the decoded bytes.
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme
*/
public
byte
[]
decode
(
String
src
)
{
return
decode
(
src
.
getBytes
(
StandardCharsets
.
ISO_8859_1
));
}
/**
* Decodes all bytes from the input byte array using the {@link Base64}
* encoding scheme, writing the results into the given output byte array,
* starting at offset 0.
*
* <p> It is the responsibility of the invoker of this method to make
* sure the output byte array {@code dst} has enough space for decoding
* all bytes from the input byte array. No bytes will be be written to
* the output byte array if the output byte array is not big enough.
*
* <p> If the input byte array is not in valid Base64 encoding scheme
* then some bytes may have been written to the output byte array before
* IllegalargumentException is thrown.
*
* @param src
* the byte array to decode
* @param dst
* the output byte array
*
* @return The number of bytes written to the output byte array
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme, or {@code dst}
* does not have enough space for decoding all input bytes.
*/
public
int
decode
(
byte
[]
src
,
byte
[]
dst
)
{
int
len
=
outLength
(
src
,
0
,
src
.
length
);
if
(
dst
.
length
<
len
)
throw
new
IllegalArgumentException
(
"Output byte array is too small for decoding all input bytes"
);
return
decode0
(
src
,
0
,
src
.
length
,
dst
);
}
/**
* Decodes all bytes from the input byte buffer using the {@link Base64}
* encoding scheme, writing the results into a newly-allocated ByteBuffer.
*
* <p> Upon return, the source buffer's position will be updated to
* its limit; its limit will not have been changed. The returned
* output buffer's position will be zero and its limit will be the
* number of resulting decoded bytes
*
* <p> {@code IllegalArgumentException} is thrown if the input buffer
* is not in valid Base64 encoding scheme. The position of the input
* buffer will not be advanced in this case.
*
* @param buffer
* the ByteBuffer to decode
*
* @return A newly-allocated byte buffer containing the decoded bytes
*
* @throws IllegalArgumentException
* if {@code src} is not in valid Base64 scheme.
*/
public
ByteBuffer
decode
(
ByteBuffer
buffer
)
{
int
pos0
=
buffer
.
position
();
try
{
byte
[]
src
;
int
sp
,
sl
;
if
(
buffer
.
hasArray
())
{
src
=
buffer
.
array
();
sp
=
buffer
.
arrayOffset
()
+
buffer
.
position
();
sl
=
buffer
.
arrayOffset
()
+
buffer
.
limit
();
buffer
.
position
(
buffer
.
limit
());
}
else
{
src
=
new
byte
[
buffer
.
remaining
()];
buffer
.
get
(
src
);
sp
=
0
;
sl
=
src
.
length
;
}
byte
[]
dst
=
new
byte
[
outLength
(
src
,
sp
,
sl
)];
return
ByteBuffer
.
wrap
(
dst
,
0
,
decode0
(
src
,
sp
,
sl
,
dst
));
}
catch
(
IllegalArgumentException
iae
)
{
buffer
.
position
(
pos0
);
throw
iae
;
}
}
/**
* Returns an input stream for decoding {@link Base64} encoded byte stream.
*
* <p> The {@code read} methods of the returned {@code InputStream} will
* throw {@code IOException} when reading bytes that cannot be decoded.
*
* <p> Closing the returned input stream will close the underlying
* input stream.
*
* @param is
* the input stream
*
* @return the input stream for decoding the specified Base64 encoded
* byte stream
*/
public
InputStream
wrap
(
InputStream
is
)
{
Objects
.
requireNonNull
(
is
);
return
new
DecInputStream
(
is
,
isURL
?
fromBase64URL
:
fromBase64
,
isMIME
);
}
private
int
outLength
(
byte
[]
src
,
int
sp
,
int
sl
)
{
int
[]
base64
=
isURL
?
fromBase64URL
:
fromBase64
;
int
paddings
=
0
;
int
len
=
sl
-
sp
;
if
(
len
==
0
)
return
0
;
if
(
len
<
2
)
{
if
(
isMIME
&&
base64
[
0
]
==
-
1
)
return
0
;
throw
new
IllegalArgumentException
(
"Input byte[] should at least have 2 bytes for base64 bytes"
);
}
if
(
isMIME
)
{
// scan all bytes to fill out all non-alphabet. a performance
// trade-off of pre-scan or Arrays.copyOf
int
n
=
0
;
while
(
sp
<
sl
)
{
int
b
=
src
[
sp
++]
&
0xff
;
if
(
b
==
'='
)
{
len
-=
(
sl
-
sp
+
1
);
break
;
}
if
((
b
=
base64
[
b
])
==
-
1
)
n
++;
}
len
-=
n
;
}
else
{
if
(
src
[
sl
-
1
]
==
'='
)
{
paddings
++;
if
(
src
[
sl
-
2
]
==
'='
)
paddings
++;
}
}
if
(
paddings
==
0
&&
(
len
&
0x3
)
!=
0
)
paddings
=
4
-
(
len
&
0x3
);
return
3
*
((
len
+
3
)
/
4
)
-
paddings
;
}
private
int
decode0
(
byte
[]
src
,
int
sp
,
int
sl
,
byte
[]
dst
)
{
int
[]
base64
=
isURL
?
fromBase64URL
:
fromBase64
;
int
dp
=
0
;
int
bits
=
0
;
int
shiftto
=
18
;
// pos of first byte of 4-byte atom
while
(
sp
<
sl
)
{
int
b
=
src
[
sp
++]
&
0xff
;
if
((
b
=
base64
[
b
])
<
0
)
{
if
(
b
==
-
2
)
{
// padding byte '='
// = shiftto==18 unnecessary padding
// x= shiftto==12 a dangling single x
// x to be handled together with non-padding case
// xx= shiftto==6&&sp==sl missing last =
// xx=y shiftto==6 last is not =
if
(
shiftto
==
6
&&
(
sp
==
sl
||
src
[
sp
++]
!=
'='
)
||
shiftto
==
18
)
{
throw
new
IllegalArgumentException
(
"Input byte array has wrong 4-byte ending unit"
);
}
break
;
}
if
(
isMIME
)
// skip if for rfc2045
continue
;
else
throw
new
IllegalArgumentException
(
"Illegal base64 character "
+
Integer
.
toString
(
src
[
sp
-
1
],
16
));
}
bits
|=
(
b
<<
shiftto
);
shiftto
-=
6
;
if
(
shiftto
<
0
)
{
dst
[
dp
++]
=
(
byte
)(
bits
>>
16
);
dst
[
dp
++]
=
(
byte
)(
bits
>>
8
);
dst
[
dp
++]
=
(
byte
)(
bits
);
shiftto
=
18
;
bits
=
0
;
}
}
// reached end of byte array or hit padding '=' characters.
if
(
shiftto
==
6
)
{
dst
[
dp
++]
=
(
byte
)(
bits
>>
16
);
}
else
if
(
shiftto
==
0
)
{
dst
[
dp
++]
=
(
byte
)(
bits
>>
16
);
dst
[
dp
++]
=
(
byte
)(
bits
>>
8
);
}
else
if
(
shiftto
==
12
)
{
// dangling single "x", incorrectly encoded.
throw
new
IllegalArgumentException
(
"Last unit does not have enough valid bits"
);
}
// anything left is invalid, if is not MIME.
// if MIME, ignore all non-base64 character
while
(
sp
<
sl
)
{
if
(
isMIME
&&
base64
[
src
[
sp
++]]
<
0
)
continue
;
throw
new
IllegalArgumentException
(
"Input byte array has incorrect ending byte at "
+
sp
);
}
return
dp
;
}
}
/*
* An output stream for encoding bytes into the Base64.
*/
private
static
class
EncOutputStream
extends
FilterOutputStream
{
private
int
leftover
=
0
;
private
int
b0
,
b1
,
b2
;
private
boolean
closed
=
false
;
private
final
char
[]
base64
;
// byte->base64 mapping
private
final
byte
[]
newline
;
// line separator, if needed
private
final
int
linemax
;
private
final
boolean
doPadding
;
// whether or not to pad
private
int
linepos
=
0
;
EncOutputStream
(
OutputStream
os
,
char
[]
base64
,
byte
[]
newline
,
int
linemax
,
boolean
doPadding
)
{
super
(
os
);
this
.
base64
=
base64
;
this
.
newline
=
newline
;
this
.
linemax
=
linemax
;
this
.
doPadding
=
doPadding
;
}
@Override
public
void
write
(
int
b
)
throws
IOException
{
byte
[]
buf
=
new
byte
[
1
];
buf
[
0
]
=
(
byte
)(
b
&
0xff
);
write
(
buf
,
0
,
1
);
}
private
void
checkNewline
()
throws
IOException
{
if
(
linepos
==
linemax
)
{
out
.
write
(
newline
);
linepos
=
0
;
}
}
@Override
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
if
(
closed
)
throw
new
IOException
(
"Stream is closed"
);
if
(
off
<
0
||
len
<
0
||
len
>
b
.
length
-
off
)
throw
new
ArrayIndexOutOfBoundsException
();
if
(
len
==
0
)
return
;
if
(
leftover
!=
0
)
{
if
(
leftover
==
1
)
{
b1
=
b
[
off
++]
&
0xff
;
len
--;
if
(
len
==
0
)
{
leftover
++;
return
;
}
}
b2
=
b
[
off
++]
&
0xff
;
len
--;
checkNewline
();
out
.
write
(
base64
[
b0
>>
2
]);
out
.
write
(
base64
[(
b0
<<
4
)
&
0x3f
|
(
b1
>>
4
)]);
out
.
write
(
base64
[(
b1
<<
2
)
&
0x3f
|
(
b2
>>
6
)]);
out
.
write
(
base64
[
b2
&
0x3f
]);
linepos
+=
4
;
}
int
nBits24
=
len
/
3
;
leftover
=
len
-
(
nBits24
*
3
);
while
(
nBits24
--
>
0
)
{
checkNewline
();
int
bits
=
(
b
[
off
++]
&
0xff
)
<<
16
|
(
b
[
off
++]
&
0xff
)
<<
8
|
(
b
[
off
++]
&
0xff
);
out
.
write
(
base64
[(
bits
>>>
18
)
&
0x3f
]);
out
.
write
(
base64
[(
bits
>>>
12
)
&
0x3f
]);
out
.
write
(
base64
[(
bits
>>>
6
)
&
0x3f
]);
out
.
write
(
base64
[
bits
&
0x3f
]);
linepos
+=
4
;
}
if
(
leftover
==
1
)
{
b0
=
b
[
off
++]
&
0xff
;
}
else
if
(
leftover
==
2
)
{
b0
=
b
[
off
++]
&
0xff
;
b1
=
b
[
off
++]
&
0xff
;
}
}
@Override
public
void
close
()
throws
IOException
{
if
(!
closed
)
{
closed
=
true
;
if
(
leftover
==
1
)
{
checkNewline
();
out
.
write
(
base64
[
b0
>>
2
]);
out
.
write
(
base64
[(
b0
<<
4
)
&
0x3f
]);
if
(
doPadding
)
{
out
.
write
(
'='
);
out
.
write
(
'='
);
}
}
else
if
(
leftover
==
2
)
{
checkNewline
();
out
.
write
(
base64
[
b0
>>
2
]);
out
.
write
(
base64
[(
b0
<<
4
)
&
0x3f
|
(
b1
>>
4
)]);
out
.
write
(
base64
[(
b1
<<
2
)
&
0x3f
]);
if
(
doPadding
)
{
out
.
write
(
'='
);
}
}
leftover
=
0
;
out
.
close
();
}
}
}
/*
* An input stream for decoding Base64 bytes
*/
private
static
class
DecInputStream
extends
InputStream
{
private
final
InputStream
is
;
private
final
boolean
isMIME
;
private
final
int
[]
base64
;
// base64 -> byte mapping
private
int
bits
=
0
;
// 24-bit buffer for decoding
private
int
nextin
=
18
;
// next available "off" in "bits" for input;
// -> 18, 12, 6, 0
private
int
nextout
=
-
8
;
// next available "off" in "bits" for output;
// -> 8, 0, -8 (no byte for output)
private
boolean
eof
=
false
;
private
boolean
closed
=
false
;
DecInputStream
(
InputStream
is
,
int
[]
base64
,
boolean
isMIME
)
{
this
.
is
=
is
;
this
.
base64
=
base64
;
this
.
isMIME
=
isMIME
;
}
private
byte
[]
sbBuf
=
new
byte
[
1
];
@Override
public
int
read
()
throws
IOException
{
return
read
(
sbBuf
,
0
,
1
)
==
-
1
?
-
1
:
sbBuf
[
0
]
&
0xff
;
}
@Override
public
int
read
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
if
(
closed
)
throw
new
IOException
(
"Stream is closed"
);
if
(
eof
&&
nextout
<
0
)
// eof and no leftover
return
-
1
;
if
(
off
<
0
||
len
<
0
||
len
>
b
.
length
-
off
)
throw
new
IndexOutOfBoundsException
();
int
oldOff
=
off
;
if
(
nextout
>=
0
)
{
// leftover output byte(s) in bits buf
do
{
if
(
len
==
0
)
return
off
-
oldOff
;
b
[
off
++]
=
(
byte
)(
bits
>>
nextout
);
len
--;
nextout
-=
8
;
}
while
(
nextout
>=
0
);
bits
=
0
;
}
while
(
len
>
0
)
{
int
v
=
is
.
read
();
if
(
v
==
-
1
)
{
eof
=
true
;
if
(
nextin
!=
18
)
{
if
(
nextin
==
12
)
throw
new
IOException
(
"Base64 stream has one un-decoded dangling byte."
);
// treat ending xx/xxx without padding character legal.
// same logic as v == '=' below
b
[
off
++]
=
(
byte
)(
bits
>>
(
16
));
len
--;
if
(
nextin
==
0
)
{
// only one padding byte
if
(
len
==
0
)
{
// no enough output space
bits
>>=
8
;
// shift to lowest byte
nextout
=
0
;
}
else
{
b
[
off
++]
=
(
byte
)
(
bits
>>
8
);
}
}
}
if
(
off
==
oldOff
)
return
-
1
;
else
return
off
-
oldOff
;
}
if
(
v
==
'='
)
{
// padding byte(s)
// = shiftto==18 unnecessary padding
// x= shiftto==12 dangling x, invalid unit
// xx= shiftto==6 && missing last '='
// xx=y or last is not '='
if
(
nextin
==
18
||
nextin
==
12
||
nextin
==
6
&&
is
.
read
()
!=
'='
)
{
throw
new
IOException
(
"Illegal base64 ending sequence:"
+
nextin
);
}
b
[
off
++]
=
(
byte
)(
bits
>>
(
16
));
len
--;
if
(
nextin
==
0
)
{
// only one padding byte
if
(
len
==
0
)
{
// no enough output space
bits
>>=
8
;
// shift to lowest byte
nextout
=
0
;
}
else
{
b
[
off
++]
=
(
byte
)
(
bits
>>
8
);
}
}
eof
=
true
;
break
;
}
if
((
v
=
base64
[
v
])
==
-
1
)
{
if
(
isMIME
)
// skip if for rfc2045
continue
;
else
throw
new
IOException
(
"Illegal base64 character "
+
Integer
.
toString
(
v
,
16
));
}
bits
|=
(
v
<<
nextin
);
if
(
nextin
==
0
)
{
nextin
=
18
;
// clear for next
nextout
=
16
;
while
(
nextout
>=
0
)
{
b
[
off
++]
=
(
byte
)(
bits
>>
nextout
);
len
--;
nextout
-=
8
;
if
(
len
==
0
&&
nextout
>=
0
)
{
// don't clean "bits"
return
off
-
oldOff
;
}
}
bits
=
0
;
}
else
{
nextin
-=
6
;
}
}
return
off
-
oldOff
;
}
@Override
public
int
available
()
throws
IOException
{
if
(
closed
)
throw
new
IOException
(
"Stream is closed"
);
return
is
.
available
();
// TBD:
}
@Override
public
void
close
()
throws
IOException
{
if
(!
closed
)
{
closed
=
true
;
is
.
close
();
}
}
}
}
src/main/java/tech/starwin/utils/BitmapUtils.java
View file @
e371b4b8
...
@@ -6,8 +6,10 @@ import android.graphics.Matrix;
...
@@ -6,8 +6,10 @@ import android.graphics.Matrix;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
android.graphics.drawable.Drawable
;
import
android.media.ExifInterface
;
import
android.media.ExifInterface
;
import
android.util.Base64
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
java.io.FileOutputStream
;
...
@@ -61,6 +63,20 @@ public class BitmapUtils {
...
@@ -61,6 +63,20 @@ public class BitmapUtils {
return
resizedBitmap
;
return
resizedBitmap
;
}
}
/**
* 缩放图片到指定大小(保持比例)
*/
public
static
Bitmap
scaleBitmap
(
Bitmap
bitmap
,
float
scale
)
{
if
(
scale
==
0
||
scale
==
1
)
{
return
bitmap
;
}
Matrix
matrix
=
new
Matrix
();
matrix
.
postScale
(
scale
,
scale
);
Bitmap
resizedBitmap
=
Bitmap
.
createBitmap
(
bitmap
,
0
,
0
,
bitmap
.
getWidth
(),
bitmap
.
getHeight
(),
matrix
,
true
);
return
resizedBitmap
;
}
/**
/**
* 从SD卡中加载图片中心区域
* 从SD卡中加载图片中心区域
...
@@ -267,6 +283,53 @@ public class BitmapUtils {
...
@@ -267,6 +283,53 @@ public class BitmapUtils {
/**
/**
* bitmap转为base64
*
* @param bitmap
* @return
*/
public
static
String
bitmapToBase64
(
Bitmap
bitmap
)
{
String
result
=
null
;
ByteArrayOutputStream
baos
=
null
;
try
{
if
(
bitmap
!=
null
)
{
baos
=
new
ByteArrayOutputStream
();
bitmap
.
compress
(
Bitmap
.
CompressFormat
.
JPEG
,
100
,
baos
);
baos
.
flush
();
baos
.
close
();
byte
[]
bitmapBytes
=
baos
.
toByteArray
();
result
=
Base64
.
encodeToString
(
bitmapBytes
,
Base64
.
DEFAULT
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
try
{
if
(
baos
!=
null
)
{
baos
.
flush
();
baos
.
close
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
return
result
;
}
/**
* base64转为bitmap
*
* @param base64Data
* @return
*/
public
static
Bitmap
base64ToBitmap
(
String
base64Data
)
{
byte
[]
bytes
=
Base64
.
decode
(
base64Data
,
Base64
.
DEFAULT
);
return
BitmapFactory
.
decodeByteArray
(
bytes
,
0
,
bytes
.
length
);
}
/**
* Drawable转Bitmap
* Drawable转Bitmap
*/
*/
public
static
Bitmap
drawableToBmp
(
Drawable
drawable
)
{
public
static
Bitmap
drawableToBmp
(
Drawable
drawable
)
{
...
...
src/main/java/tech/starwin/utils/FileUtils.java
View file @
e371b4b8
...
@@ -62,7 +62,8 @@ public class FileUtils {
...
@@ -62,7 +62,8 @@ public class FileUtils {
* 创建图片文件
* 创建图片文件
*/
*/
public
static
File
getImageFile
(
Context
context
,
String
fileName
)
{
public
static
File
getImageFile
(
Context
context
,
String
fileName
)
{
File
file
=
new
File
(
getAppDir
(
context
).
getAbsoluteFile
()
+
IMAGE_CACHE
);
File
file
=
new
File
(
context
.
getExternalFilesDir
(
null
).
getAbsoluteFile
()
+
IMAGE_CACHE
);
// File file = new File(getAppDir(context).getAbsoluteFile() + IMAGE_CACHE);
if
(!
file
.
exists
())
{
if
(!
file
.
exists
())
{
file
.
mkdirs
();
file
.
mkdirs
();
}
}
...
...
src/main/java/tech/starwin/utils/SPDataProvider.java
0 → 100644
View file @
e371b4b8
package
tech
.
starwin
.
utils
;
import
android.graphics.Bitmap
;
import
android.text.TextUtils
;
/**
* Created by SiKang on 2019/4/22.
*/
public
class
SPDataProvider
{
//
// /**
// * 存取KTP照片
// */
// public static void saveKTPImage(Bitmap bitmap) {
// PreferencesManager.get().saveData("ktp_image", BitmapUtils.bitmapToBase64(bitmap));
// }
// public static Bitmap getKTPImage() {
// String bitmapStr = PreferencesManager.get().getString("ktp_image", "");
// return TextUtils.isEmpty(bitmapStr) ? null : BitmapUtils.base64ToBitmap(bitmapStr);
// }
//
// /**
// * 存取工作证照片
// */
// public static void saveWorkImage(Bitmap bitmap) {
// PreferencesManager.get().saveData("work_card_image", BitmapUtils.bitmapToBase64(bitmap));
// }
// public static Bitmap getWorkImage() {
// String bitmapStr = PreferencesManager.get().getString("work_card_image", "");
// return TextUtils.isEmpty(bitmapStr) ? null : BitmapUtils.base64ToBitmap(bitmapStr);
// }
}
src/main/java/tech/starwin/utils/context_utils/PermissionsHelper.java
View file @
e371b4b8
...
@@ -56,10 +56,10 @@ public class PermissionsHelper {
...
@@ -56,10 +56,10 @@ public class PermissionsHelper {
Manifest
.
permission
.
READ_CONTACTS
,
Manifest
.
permission
.
READ_CONTACTS
,
Manifest
.
permission
.
READ_CALL_LOG
,
Manifest
.
permission
.
READ_CALL_LOG
,
Manifest
.
permission
.
READ_SMS
,
Manifest
.
permission
.
READ_SMS
,
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
,
//
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
//
Manifest.permission.WRITE_EXTERNAL_STORAGE
//
Manifest.permission.ACCESS_COARSE_LOCATION,//粗精度定位
Manifest
.
permission
.
ACCESS_COARSE_LOCATION
,
//粗精度定位
//
Manifest.permission.ACCESS_FINE_LOCATION//卫星定位
Manifest
.
permission
.
ACCESS_FINE_LOCATION
//卫星定位
// Manifest.permission.READ_PHONE_STATE
// Manifest.permission.READ_PHONE_STATE
};
};
...
@@ -70,8 +70,8 @@ public class PermissionsHelper {
...
@@ -70,8 +70,8 @@ public class PermissionsHelper {
Manifest
.
permission
.
READ_CONTACTS
,
Manifest
.
permission
.
READ_CONTACTS
,
// Manifest.permission.READ_CALL_LOG,
// Manifest.permission.READ_CALL_LOG,
// Manifest.permission.READ_SMS,
// Manifest.permission.READ_SMS,
Manifest
.
permission
.
READ_EXTERNAL_STORAGE
,
//
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
//
Manifest.permission.WRITE_EXTERNAL_STORAGE
// Manifest.permission.ACCESS_COARSE_LOCATION,//粗精度定位
// Manifest.permission.ACCESS_COARSE_LOCATION,//粗精度定位
// Manifest.permission.ACCESS_FINE_LOCATION//卫星定位
// Manifest.permission.ACCESS_FINE_LOCATION//卫星定位
// Manifest.permission.READ_PHONE_STATE
// Manifest.permission.READ_PHONE_STATE
...
...
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