Android如何新增圖片
阿新 • • 發佈:2018-12-29
Android如何新增圖片
一、目標
通過在文章中插入圖片,實現圖文混排的功能。
二、下載地址
神馬筆記最新版本:【神馬筆記Version1.1.0_beta.apk】
三、獲取圖片
有2種途徑可以獲取圖片
- 拍照(建立新的照片)
- 照片相簿(選擇手機上的照片)
在Android平臺,有2種方式可以用來實現這2種途徑
- 呼叫第三方應用
- 編寫拍照與相簿程式碼,自己實現之
前者在功能上可能會遇到一些限制,但工作量小。
後者更加靈活,可以隨意發揮,但工作量較大。雖然可以在Github上找到不錯的實現方案,終歸需要一些除錯的事件。
神馬筆記採用的是第一種方式——呼叫第三方應用。
四、呼叫第三方應用
Android通過startActivityForResult
呼叫地方應用,並且通過onActivityResult
處理返回結果。這2個方法分別存在於Activity
Fragment
中。
Activity#startActivityForResult
Activity#onActivityResult
Fragment#startActivityForResult
Fragment#onActivityResult
1. 呼叫拍照應用
public boolean request() {
SoftInputUtils.hide(context);
Uri imageUri;
{
File file = target.getFile();
file. getAbsoluteFile().getParentFile().mkdirs();
imageUri = UriUtils.fromFile(context, file);
}
Intent intent = new Intent();
{
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
}
try {
parent.startActivityForResult(intent, requestCode);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
2. 呼叫照片相簿應用
public boolean request() {
SoftInputUtils.hide(context);
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
try {
parent.startActivityForResult(intent, requestCode);
return true;
} catch (Exception e) {
}
return false;
}
五、優化呼叫過程
startActivityForResult
和onActivityResult
這2個介面通過requestCode
識別請求及結果。為了避免定義常量傳送請求以及使用switch語法處理結果,採用面向物件的方法來優化呼叫過程。
1. 定義呼叫處理類
public abstract class BaseRequestDelegate implements BiConsumer<Integer, Intent> {
private static int COUNTER = 1;
protected int requestCode;
protected Fragment parent;
protected Activity context;
public BaseRequestDelegate(Fragment f) {
this.context = f.getActivity();
this.parent = f;
this.requestCode = COUNTER;
{
int counter = COUNTER;
++counter;
counter %= 1000;
COUNTER = counter;
}
}
public int getRequestCode() {
return requestCode;
}
public abstract boolean request();
public abstract void accept(Integer resultCode, Intent data);
}
BaseRequestDelegate
會自動產生requestCode
,避免定義常量。這裡使用了是COUNTER的方式,每次建立一個新的請求,計數器累加1作為下一次的requestCode
,並且限定在1000以內。
BaseRequestDelegate
封裝了2個方法request
用與傳送請求,以及accept
用於處理結果。
2. 定義呼叫管理類
public class RequestResultManager {
HashMap<Integer, BiConsumer<Integer, Intent>> map;
public RequestResultManager() {
this.map = new HashMap<>();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
BiConsumer delegate = map.remove(requestCode);
if (delegate != null) {
delegate.accept(resultCode, data);
}
}
public void request(BaseRequestDelegate delegate) {
boolean result = delegate.request();
if (result) {
map.put(delegate.getRequestCode(), delegate);
}
}
}
RequestResultManager
負責管理BaseRequestDelegate
,通過request
方法傳送請求。在onActivityResult
處理結果。
3. 優化呼叫過程
- 呼叫第三方應用
void requestInsertion() {
MenuItemClickListener listener = new MenuItemClickListener();
{
listener.put(R.id.menu_insert_paragraph, e ->
new ParagraphInsertion(insertionCallback).execute()
);
listener.put(R.id.menu_camera, e -> {
CameraDelegate delegate = new CameraDelegate(this, insertionCallback);
requestResultManager.request(delegate);
});
listener.put(R.id.menu_photo, e -> {
PhotoDelegate delegate = new PhotoDelegate(this, insertionCallback);
requestResultManager.request(delegate);
});
}
PopupMenuDialogFragment dialogFragment = new PopupMenuDialogFragment();
dialogFragment.setTheme(R.style.DialogDimTheme);
dialogFragment.setMenuResource(R.menu.menu_compose_insertion);
dialogFragment.setOnMenuItemClickListener(listener);
dialogFragment.showNow(getFragmentManager(), "insertion");
}
- 處理呼叫結果
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
requestResultManager.onActivityResult(requestCode, resultCode, data);
}
六、Final
通過呼叫第三方拍照及相簿應用,可以快速實現文章中插入圖片的功能。但是無法進一步操作第三方應用,使用靈活性較低。比如,呼叫相簿應用新增某一相簿下的圖片,需要多次選擇,無法記錄最近一次使用的相簿就頗為麻煩。