Picture,Image Upload to Server

AndroidManifest.xml

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.location.gps" />

build.gradle

    //통신
    implementation 'dev.dworks.libs:volleyplus:+'
    implementation "gun0912.ted:tedpermission:2.1.0"
    implementation group: 'cz.msebera.android' , name: 'httpclient' , version: '4.4.1.1'
    //이미지 crop
    implementation 'com.squareup.picasso:picasso:2.3.3'

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".frag.MyFragment">
    <!--CardView를 이용해 프로필 사진 이너라인을 적용-->
    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="24dp"
        app:cardCornerRadius="100dp"
        app:cardElevation="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="MissingConstraints">
        <ImageView
            android:id="@+id/my_img"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:src="@drawable/ic_launcher_foreground" />
    </androidx.cardview.widget.CardView>
 </androidx.constraintlayout.widget.ConstraintLayout>

URLConnector.java

import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLConnector extends Thread {
    private String result;
    private String URL;
    public URLConnector(String url){
        URL = url;
    }
    @Override
    public void run() {
        final String output = request(URL);
        result = output;
    }
    public String getResult(){
        return result;
    }
    private String request(String urlStr) {
        StringBuilder output = new StringBuilder();
        try {
            java.net.URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            if (conn != null) {
                conn.setConnectTimeout(10000);
                conn.setRequestMethod("GET");
                conn.setDoInput(true);
                conn.setDoOutput(true);
                int resCode = conn.getResponseCode();
                if (resCode == HttpURLConnection.HTTP_OK) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())) ;
                    String line = null;
                    while(true) {
                        line = reader.readLine();
                        if (line == null) {
                            break;
                        }
                        output.append(line + "\n");
                    }
                    reader.close();
                    conn.disconnect();
                }
            }
        } catch(Exception ex) {
            Log.e("SampleHTTP", "Exception in processing response.", ex);
            ex.printStackTrace();
        }
        return output.toString();
    }
}

FileUploadUtils.java

import android.util.Log;
import java.io.File;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class FileUploadUtils {
    public static void send2Server(File file, String email,String partImage) {
        RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("img", file.getName(), RequestBody.create(MultipartBody.FORM, file))
                .addFormDataPart("name",email)
                .addFormDataPart("partImage",partImage)
                .build();
        Request request = new Request.Builder().url("https://서버_아이피/upload.php")
                .post(requestBody).build();
        OkHttpClient client = new OkHttpClient();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d("TEST : ", response.body().string());
            }
        });
    }
}

DrawUrlImageTask

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
public class DrawUrlImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView ivSample;
    public DrawUrlImageTask(ImageView ivSample) {
        this.ivSample = ivSample;
    }
    protected Bitmap doInBackground(String... urls) {
        String url = urls[0];
        Bitmap bitmap = null;
        InputStream in = null;
        try {
            in = new java.net.URL(url).openStream();
            bitmap = BitmapFactory.decodeStream(in);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                in.close();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bitmap;
    }
    protected void onPostExecute(Bitmap bitmap) {
        ivSample.setImageBitmap(bitmap);
    }
}

MyService.java (Service)

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import androidx.core.app.NotificationCompat;
public abstract class MyService extends Service {
    public MyService() {
    }
    @Override
    public void onCreate(){
        super.onCreate();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            startMyOwnForeground();
        else
            startForeground(1, new Notification());
    }
    private void startMyOwnForeground(){
        String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
        String channelName = "My Background Service";
        NotificationChannel chan = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan.setLightColor(Color.BLUE);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
        }
        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        assert manager != null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            manager.createNotificationChannel(chan);
        }
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setContentTitle("App is running in background")
                .setPriority(NotificationManager.IMPORTANCE_MIN)
                .setCategory(Notification.CATEGORY_SERVICE)
                .build();
        startForeground(2, notification);
    }
}

CameraFragment.java

 ImageView imageView;
    //이미지처리 변수 시작
    private static final int MY_PERMISSION_CAMERA = 1111;
    private static final int REQUEST_TAKE_PHOTO = 2222;
    private static final int REQUEST_TAKE_ALBUM = 3333;
    private static final int REQUEST_IMAGE_CROP = 4444;
    String mCurrentPhotoPath;
    File imageFile = null;
    Uri imageUri;
    Uri photoURI, albumURI;
    private static final String TAG = "blackjin";
    private Boolean isPermission = true;
public class CameraFragment extends Fragment {
 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_my, container, false);
        mContext = v.getContext();
       final String serverURL = "서버_아이피/imagedbSelect.php";
        final SharedPreferences sharedPreferences = getActivity().getSharedPreferences("login",getActivity().MODE_PRIVATE);
        final SharedPreferences.Editor editor = sharedPreferences.edit();
        this.email = sharedPreferences.getString("rememberId","");
        this.name = sharedPreferences.getString("rememberName","");
        imageView = v.findViewById(R.id.my_img);
        Toast.makeText(mContext, "email : "+email, Toast.LENGTH_SHORT).show();
        checkPermission();
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AlertDialog.Builder(mContext)
                .setTitle("이미지 선택")
                        .setPositiveButton("갤러리", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if(isPermission) getAlbum();
                                else Toast.makeText(mContext, getResources().getString(R.string.permission_2), Toast.LENGTH_LONG).show();
                            }
                        })
                        .setNegativeButton("카메라", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if(isPermission) captureCamera();
                                else Toast.makeText(mContext, getResources().getString(R.string.permission_2), Toast.LENGTH_LONG).show();
                            }
                        })
                        .create().show();
            }
        });
        URLConnector task = new URLConnector(serverURL+"?name="+email+"&partimg="+"ProfileImage");
        task.start();
        try{
            task.join();
            System.out.println("waiting... for result");
        }
        catch(InterruptedException e){
        }
        //return된 json데이터
        String result = task.getResult();
        showJson(result);
        Log.e("Mycat",result);
        return v;
    }
    //데이터처리
    private void showJson(String json){
        String TAG_JSON="result";
        String TAG_ID = "id";
        String TAG_NAME = "name";
        String TAG_PARTIMG ="partimg";
        String TAG_IMG ="image";
        String TAG_DATE ="date";
        try {
            JSONObject jsonObject = new JSONObject(json);
            JSONArray jsonArray = jsonObject.getJSONArray(TAG_JSON);
            for(int i=0;i<jsonArray.length();i++){
                JSONObject item = jsonArray.getJSONObject(i);
                String id = item.getString(TAG_ID);
                String name = item.getString(TAG_NAME);
                String partimg = item.getString(TAG_PARTIMG);
                String img = item.getString(TAG_IMG);
                String date = item.getString(TAG_DATE);
                //이미지 url 불러와 이미지 적용
                new DrawUrlImageTask((ImageView) imageView)
                        .execute("서버_주소/"+img);
            }
        } catch (JSONException e) {
            Log.d(TAG, "showResult : ", e);
        }
    }
    //이하 이미지처리
    private void captureCamera(){
        String state = Environment.getExternalStorageState();
        // 외장 메모리 검사
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
                imageFile = null;
                try {
                    imageFile = createImageFile();
                } catch (IOException ex) {
                    Log.e("captureCamera Error", ex.toString());
                }
                if (imageFile != null) {
                    // getUriForFile의 두 번째 인자는 Manifest provier의 authorites와 일치해야 함
                    Uri providerURI = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName(), imageFile);
                    imageUri = providerURI;
                    // 인텐트에 전달할 때는 FileProvier의 Return값인 content://로만!!, providerURI의 값에 카메라 데이터를 넣어 보냄
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, providerURI);
                    startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
                }
            }
        } else {
            Toast.makeText(mContext, "저장공간이 접근 불가능한 기기입니다", Toast.LENGTH_SHORT).show();
            return;
        }
    }
    public File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + ".jpg";
        File storageDir = new File(Environment.getExternalStorageDirectory() + "/Pictures", "gyeom");
        if (!storageDir.exists()) {
            Log.i("mCurrentPhotoPath1", storageDir.toString());
            storageDir.mkdirs();
        }
        imageFile = new File(storageDir, imageFileName);
        mCurrentPhotoPath = imageFile.getAbsolutePath();
        return imageFile;
    }
    private void getAlbum(){
        Log.i("getAlbum", "Call");
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        intent.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
        startActivityForResult(intent, REQUEST_TAKE_ALBUM);
    }
    private void galleryAddPic(){
        Log.i("galleryAddPic", "Call");
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        // 해당 경로에 있는 파일을 객체화(새로 파일을 만든다는 것으로 이해하면 안 됨)
        imageFile = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(imageFile);
        mediaScanIntent.setData(contentUri);
        getActivity().sendBroadcast(mediaScanIntent);
        Toast.makeText(mContext, "사진이 앨범에 저장되었습니다.", Toast.LENGTH_SHORT).show();
    }
    // 카메라 전용 크랍
    public void cropImage(){
        Log.i("cropImage", "Call");
        Log.i("cropImage", "photoURI : " + photoURI + " / albumURI : " + albumURI);
        Intent cropIntent = new Intent("com.android.camera.action.CROP");
        // 50x50픽셀미만은 편집할 수 없다는 문구 처리 + 갤러리, 포토 둘다 호환하는 방법
        cropIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        cropIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        cropIntent.setDataAndType(photoURI, "image/*");
        //cropIntent.putExtra("outputX", 200); // crop한 이미지의 x축 크기, 결과물의 크기
        //cropIntent.putExtra("outputY", 200); // crop한 이미지의 y축 크기
        cropIntent.putExtra("aspectX", 1); // crop 박스의 x축 비율, 1&1이면 정사각형
        cropIntent.putExtra("aspectY", 1); // crop 박스의 y축 비율
        cropIntent.putExtra("scale", true);
        cropIntent.putExtra("output", albumURI); // 크랍된 이미지를 해당 경로에 저장
        startActivityForResult(cropIntent, REQUEST_IMAGE_CROP);
    }
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_TAKE_PHOTO:
                if (resultCode == Activity.RESULT_OK) {
                    try {
                        Log.i("REQUEST_TAKE_PHOTO", "OK");
                        galleryAddPic();
                        imageView.setImageURI(imageUri);
                        FileUploadUtils.send2Server(imageFile,email,"ProfileImage");
                    } catch (Exception e) {
                        Log.e("REQUEST_TAKE_PHOTO", e.toString());
                    }
                } else {
                    Toast.makeText(mContext, "사진찍기를 취소하였습니다.", Toast.LENGTH_SHORT).show();
                }
                break;
            case REQUEST_TAKE_ALBUM:
                if (resultCode == Activity.RESULT_OK) {
                    if(data.getData() != null){
                        try {
                            imageFile = null;
                            imageFile = createImageFile();
                            photoURI = data.getData();
                            albumURI = Uri.fromFile(imageFile);
                            cropImage();
                        }catch (Exception e){
                            Log.e("TAKE_ALBUM_SINGLE ERROR", e.toString());
                        }
                    }
                }
                break;
            case REQUEST_IMAGE_CROP:
                if (resultCode == Activity.RESULT_OK) {
                    galleryAddPic();
                    imageView.setImageURI(albumURI);
                    FileUploadUtils.send2Server(imageFile,email,"ProfileImage");
                }
                break;
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSION_CAMERA:
                for (int i = 0; i < grantResults.length; i++) {
                    // grantResults[] : 허용된 권한은 0, 거부한 권한은 -1
                    if (grantResults[i] < 0) {
                        Toast.makeText(mContext, "해당 권한을 활성화 하셔야 합니다.", Toast.LENGTH_SHORT).show();
                        return;
                    }
                }
                // 허용했다면 이 부분에서..
                break;
        }
    }
    //권한설정
    private void checkPermission(){
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            // 처음 호출시엔 if()안의 부분은 false로 리턴 됨 -> else{..}의 요청으로 넘어감
            if ((ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) ||
                    (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA))) {
                new AlertDialog.Builder(mContext)
                        .setTitle("알림")
                        .setMessage("저장소 권한이 거부되었습니다. 사용을 원하시면 설정에서 해당 권한을 직접 허용하셔야 합니다.")
                        .setNeutralButton("설정", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                intent.setData(Uri.parse("package:" + getActivity().getPackageName()));
                                startActivity(intent);
                            }
                        })
                        .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                getActivity().finish();
                            }
                        })
                        .setCancelable(false)
                        .create()
                        .show();
            } else {
                ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, MY_PERMISSION_CAMERA);
            }
        }
    }
}

imgDTO.java

public class imgDTO {
    String name;
    String partimg;
    String img;
    String date;
    public imgDTO(String name, String partimg, String img, String date) {
        this.name = name;
        this.partimg = partimg;
        this.img = img;
        this.date = date;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPartimg() {
        return partimg;
    }
    public void setPartimg(String partimg) {
        this.partimg = partimg;
    }
    public String getImg() {
        return img;
    }
    public void setImg(String img) {
        this.img = img;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
}

upload.php

<?php
   header("Content-Type:text/html; charset=UTF-8");
    $name= $_POST['name'];
    $partImage= $_POST['partImage'];
    $file= $_FILES['img'];
    //이미지 파일을 영구보관하기 위해
    //이미지 파일의 세부정보 얻어오기
    $srcName= $file['name'];
    $tmpName= $file['tmp_name']; //php 파일을 받으면 임시저장소에 넣는다. 그곳이 tmp
    //임시 저장소 이미지를 원하는 폴더로 이동
    $dstName= "uploads/".date('Ymd_his').$srcName;
    $result=move_uploaded_file($tmpName, $dstName);
    if($result){
        echo "upload success\n";
    }else{
        echo "upload fail\n";
    }
    echo "$name\n";
    echo "$partImage\n";
    echo "$dstName\n";
    // $name, $partImage, $dstName, $now DB에 저장
    // MySQL에 접속
    $conn= mysqli_connect("localhost","id","passwd","dbname");
    //한글 깨짐 방지
    mysqli_query($conn, "set names utf8");
    //insert하는 쿼리문
    $sql="replace into magedata(name, partimg, image) values('$name','$partImage','$dstName')";
    $result =mysqli_query($conn, $sql); //쿼리를 요청하다.
    if($result) echo "insert success \n";
    else echo "insert fail \n";
   mysqli_close($conn);
?>

imagedbSelect.php

<?php
$con=mysqli_connect("localhost","id","passwd","dbname");
if (mysqli_connect_errno($con))
{
   echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$PARTIMG = $_GET['partimg'];
$NAME = $_GET['name'];
$result = mysqli_query($con,"SELECT * FROM imagedata where name='$NAME' and partimg='$PARTIMG'");
 $data = array();
 if ($result) {
	while ($row=mysqli_fetch_array($result)) {
		array_push($data,array('id'=>$row[0],'name'=>$row[1],'partimg'=>$row[2],'image'=>$row[3],'date'=>$row[4]));
	}
	header('Content-Type: application/json; charset=utf8');
	$json = json_encode(array("result"=>$data), JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE);
	echo $json; // => 출력되는 값이 이 코드로 하여금 android로 전송된다..
} else {
	echo "SQL문 처리중 에러 발생 : ";
	echo mysqli_error($con);
}
if($data){
echo $data;
}
mysqli_close($con);
?>

Leave a Comment