안드로이드에서 기본 제공하는 이메일 앱을 인텐트로 사용하지 않고,

직접 개발한 일반 앱에서 Gmail 계정을 경유하여 이메일 보내기

 

< 다운받아 설치하여야 할 라이브러리 3개>

ㅡ activation.jar   ,   additionnal.jar   ,   mail.jar

ㅡ 설치 장소 : 각 프로젝트의 "프로젝트명/libs" 폴더

ㅡ 첨부파일 3개를 PC로 다운받아서 "프로젝트명/libs" 폴더에  copy하고,

ㅡ 안드로이드 스튜디오에서 3개의 *.jar 파일에 대하여,  각각  라이브러리 import 실행

 

< 구글 계정 로그인 보안 등급 조정 >

ㅡ 송신에 사용 될 Gmail 계정의 보안등급을 하향 조정 ( 구글 홈페이지 계정보안관리 )

 

activation.jar
0.05MB
additionnal.jar
0.04MB
mail.jar
0.42MB

 

< MainActivity >

    try {
        GMailSender gMailSender = new GMailSender(myID, myPassWD);
        //GMailSender.sendMail(제목, 본문내용, 받는사람);
        gMailSender.sendMail(strTitle,     strMessage,       strPerson);
        Toast.makeText(getApplicationContext(), "송신 완료", Toast.LENGTH_SHORT).show();
        sendResultOk = true;
        button.setEnabled(false);
    } catch (SendFailedException e) {
        Toast.makeText(getApplicationContext(), "이메일 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show();
    } catch (MessagingException e) {
        Toast.makeText(getApplicationContext(), "인터넷 연결을 확인해주십시오", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        e.printStackTrace();
    }

 

 

< GMailSender >

package com.example.mygmailsend;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class GMailSender extends javax.mail.Authenticator {
    private String mailhost = "smtp.gmail.com";
    private String user ;
    private String password ;
    private Session session;
    private String emailCode;

    public GMailSender(String user, String password) {
        this.user = user;
        this.password = password;
        emailCode = createEmailCode();
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");
        props.setProperty("mail.host", mailhost);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class",
                "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");
        props.setProperty("mail.smtp.quitwait", "false");

        //구글에서 지원하는 smtp 정보를 받아와 MimeMessage 객체에 전달해준다.
        session = Session.getDefaultInstance(props, this);
    }

    public String getEmailCode() {
        return emailCode;
    } //생성된 이메일 인증코드 반환

    private String createEmailCode() { //이메일 인증코드 생성
        String[] str = {"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", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
        String newCode = new String();

        for (int x = 0; x < 8; x++) {
            int random = (int) (Math.random() * str.length);
            newCode += str[random];
        }

        return newCode;
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        //해당 메서드에서 사용자의 계정(id & password)을 받아 인증받으며 인증 실패시 기본값으로 반환됨.
        return new PasswordAuthentication(user, password);
    }

    public synchronized void sendMail(String subject, String body, String recipients) throws Exception {
        MimeMessage message = new MimeMessage(session);
        DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain")); //본문 내용을 byte단위로 쪼개어 전달
        message.setSender(new InternetAddress(user));  //본인 이메일 설정
        message.setSubject(subject); //해당 이메일의 본문 설정
        message.setDataHandler(handler);
        if (recipients.indexOf(',') > 0)
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
        else
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
        Transport.send(message); //메시지 전달
    }

    public class ByteArrayDataSource implements DataSource {
        private byte[] data;
        private String type;

        public ByteArrayDataSource(byte[] data, String type) {
            super();
            this.data = data;
            this.type = type;
        }

        public ByteArrayDataSource(byte[] data) {
            super();
            this.data = data;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getContentType() {
            if (type == null)
                return "application/octet-stream";
            else
                return type;
        }

        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(data);
        }

        public String getName() {
            return "ByteArrayDataSource";
        }

        public OutputStream getOutputStream() throws IOException {
            throw new IOException("Not Supported");
        }
    }
}

 

<AndroidManifest.xml>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mygmailsend">

    <uses-permission android:name="android.permission.INTERNET" />

 

 

주) 송신에 사용될  G메일  계정의 보안등급 하향 조정 필수

Posted by LODE_RUNNER
,

// 안드로이드 시스템에서 각각의 앱에게 할당 해 주는 디렉토리(내부 저장소)에 파일 만들어 저장하기
// - 앱이 삭제되면 이 디렉토리도 함께 삭제 됨에 유의

 

보충 설명  :  developer.android.com/training/data-storage/files/external?hl=ko#java

 

//   안드로이드 시스템에서 개별 앱에게 할당 해 주는 디렉토리에 파일 만들어 저장하기
//   - 앱이 삭제되면 이 디렉토리도 함께 삭제 됨에 유의
    
public String  LIST_To_FileSave (int list_max , final List uri_arrayB) {
    Log.d(TAG, "LIST_To_FileSave: 001");
    FileWriter fw = null;
    BufferedWriter bw = null;
    File FilePath = getPrivateDocumentsStorageDir(MainActivity.this,"text");
    String FullPath = FilePath.toString() + "/imglist.txt" ;
    try {
//      fw = new FileWriter("file:///android_asset/audio/hello.mp3", false);
        fw = new FileWriter(FullPath, false);
        bw = new BufferedWriter(fw);
        Log.d(TAG, "LIST_To_FileSave: Before For");
        for ( int forindex = 0  ;forindex <= list_max  ; forindex++ ) {
            Uri contentUri = (Uri) uri_arrayB.get(forindex);
            String UriToString = contentUri.toString() ;
            bw.write(UriToString);
            bw.newLine();
            Log.d(TAG, "LIST_To_FileSave: " + forindex );
        }
        Log.d(TAG, "LIST_To_FileSave: After For");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Log.d(TAG, "LIST_To_FileSave: FileNotFoundException ");
    } catch (Exception e) {
        e.printStackTrace();
        Log.d(TAG, "LIST_To_FileSave: Error ");
    } finally {
        Log.d(TAG, "LIST_To_FileSave: OK ");
        if (bw != null) try {
            bw.close();
        } catch (IOException e) {
        }
        if (fw != null) try {
            fw.close();
        } catch (IOException e) {
        }
    }
    Log.d(TAG, "LIST_To_FileSave: 999");
    return FullPath ;
};


//  ************************************************************************
//   안드로이드 시스템에서 개별 앱에게 할당 해 주는 디렉토리 명칭 구하기
//   - 앱이 삭제되면 이 디렉토리도 함께 삭제 됨에 유의
public File getPrivateDocumentsStorageDir(Context context, String subDir ) {
    Log.d(TAG, "getPrivateDocumentsStorageDir: ");
    File FullDir = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_DOCUMENTS), subDir );
    if (!FullDir.mkdirs()) {
        Log.e(TAG, "Sub Directory Exist");
    }
/*
    if(!FullDir.exists()){
        FullDir.mkdir();
    }
 */
    Log.d(TAG, "getPrivateDocumentsStorageDir: " + FullDir.toString() );
    return FullDir;
}


참고 ) 위에서 만든 파일을 읽어서 로그에 프린트하기

public  int    File_To_Log  (  String FullPath  ) {
    Log.d(TAG, "File_To_Log: 001");
    FileReader fr = null;
    BufferedReader br = null;
    String input_line ;
    int input_count = 0 ;
    try {
        fr = new FileReader(FullPath);
        br = new BufferedReader(fr);
        while ((input_line = br.readLine()) != null) {
            input_count ++ ;
            Log.d(TAG, "(" + input_count + ")  " +  input_line );
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (br != null) try {
            br.close();
        } catch (IOException e) {
        }
        if (fr != null) try {
            fr.close();
        } catch (IOException e) {
        }
    }
    Log.d(TAG, "File_To_Log: 999");
    return ( input_count );
}
Posted by LODE_RUNNER
,

View.post(Runnable)

 

    new Thread(new Runnable() {
        public void run() {
            // a potentially time consuming task
            final Bitmap bitmap =
                    processBitMap("image.png");
            imageView.post(new Runnable() {
                public void run() {
                    imageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();

 

 

developer.android.com/guide/components/processes-and-threads#java

 

프로세스 및 스레드 개요  |  Android 개발자  |  Android Developers

애플리케이션 구성 요소가 시작되고 애플리케이션에 실행 중인 다른 구성 요소가 없으면 Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux 프로세스를 시작합니다. 기본적으로 같은 ��

developer.android.com

 

 

Posted by LODE_RUNNER
,

첨부파일 동봉 이메일링

    Intent emailIntent = new Intent(Intent.ACTION_SEND);
    // The intent does not have a URI, so declare the "text/plain" MIME type
    emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
    emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
    emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
    // You can also attach multiple items by passing an ArrayList of Uris

 

브라우저를 선택하여 인터넷 웹 서핑

    Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
    Intent chooser = Intent.createChooser(webIntent, "■ 브라우저 선택 ■");
                                
    if (webIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(chooser);
    }  else {
		Log.d("Error", "설치된 브라우저가 없습니다.");
	}

 

 

전화 다이얼링

    Uri number = Uri.parse("tel:5551234");
    Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
    if (callIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(callIntent);
    }  else {
		Log.d("Error", "스마트 폰에 다이얼러가 없습니다 ");
	}

 

지도 앱

    // Map point based on address
    Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    // Or map point based on latitude/longitude
    // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
    if (mapIntent.resolveActivity(getPackageManager()) != null) {
        startActivity(mapIntent);
    }  else {
		Log.d("Error", "지도 앱이 없습니다 ");
	}

 

사진 선택 요청하고 되돌려 받기(1)  - 요청하기

Intent intent_img = new Intent(Intent.ACTION_PICK);
intent_img.setType("image/*");
intent_img.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent_img.setType(MediaStore.Images.Media.CONTENT_TYPE);
startActivityForResult(Intent.createChooser(intent_img,"다중 선택은 '포토'를 선택하세요."), 1);
//  1  :   REQUEST_TAKE_ALBUM

 

사진 선택 요청하고 되돌려 받기(2)  - 되돌려 받기

    protected void onActivityResult(int requestCode, int resultCode, Intent returned_intent) {
        Log.d(TAG, "( onActivityResult )");
        super.onActivityResult(requestCode, resultCode, returned_intent);

        if (resultCode != Activity.RESULT_OK) {
            Toast.makeText(MainActivity.this, "사진 선택을 취소하였습니다.", Toast.LENGTH_SHORT).show();
            Log.i("(onActivityResult)", "requestCode = " + requestCode + " , resultCode = " + resultCode);
            return;
        }
        switch (requestCode) {
            case REQUEST_TAKE_ALBUM:
                    ArrayList imageList = new ArrayList<>();
                    // 멀티 선택을 지원하지 않는 기기에서는 getClipdata()가 없음 => getData()로 접근해야 함
                    if (returned_intent.getClipData() == null) {
                        Log.i(TAG, "1. getData / single choice " + String.valueOf(returned_intent.getData()));
                        imageList.add(String.valueOf(returned_intent.getData()));
                    } else {
                        final ClipData clipData = returned_intent.getClipData();
                        Log.i(TAG , "2. clipdata " + String.valueOf(clipData.getItemCount()));
                        if (clipData.getItemCount() < 1){
                            Toast.makeText(MainActivity.this, "  사진을 선택하세요  ", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        // 멀티 선택에서 하나만 선택했을 경우
                        else if (clipData.getItemCount() == 1) {
                            forLoop = false ;
                            Thread ForThread_multi1 = new  Thread () {
                                @Override
                                public void run() {
                                        OneUri(clipData.getItemAt(0).getUri());
                                }};
                            ForThread_multi1.start() ;
                        } else if (clipData.getItemCount() > 1 && clipData.getItemCount() < 9999) {
                            show_Selected_Pictures(clipData);
                        }
                    }
            default: {
                Toast.makeText(MainActivity.this, "  여기는 사진 되돌려 받기만 처리하고 다른 기능은 처리하지 않음  ", Toast.LENGTH_SHORT).show();
                break;
            }
        }
    }
Posted by LODE_RUNNER
,

AllPictures.zip
0.14MB

전체 패키지를 zip 으로 첨부

//  스마트폰에 저장된 모든 이미지와 사진 들을 보여주기
//   ㅡ  보여주기 시간 간격 : 1초
//   ㅡ  처음부터 끝까지 순차적으로  또는  무작위(RANDOM)
//   ㅡ  사용된 기술 : 미디어스토어, 커서, 리스트, 쓰레드, 이미지뷰
//                  MediaStore, Cursor, List, Thread, ImageView
//   ㅡ  2020.7.11.  by LODE_RUNNER
//      android:label="몽땅_쑈"

package com.example.allpictures;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.Log;
import android.util.Size;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import static java.lang.Thread.sleep;

public class MainActivity extends AppCompatActivity {
    static final String KEY_DATA = "KEY_DATA";
    static String Data = "" ;
//  TextView textView;
    String[] permission_list = {
            Manifest.permission.READ_EXTERNAL_STORAGE
    };
    static Bitmap bitmap = null ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        checkPermissions();

        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            setContentView(R.layout.activity_main);
        } else {
            Data = savedInstanceState.getString(KEY_DATA);
                setContentView(R.layout.activity_main);
        }

        setContentView(R.layout.activity_main);
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .permitDiskReads()
                .permitDiskWrites()
                .permitNetwork().build());

        Thread IS_thread = new Thread() {
            @Override
            public void run() {
                int input_stream = 2 ;
                switch  ( input_stream ) {
                    case 0:   //  input_stream 비적용
                        slide_show_A();
                        break ;
                    case 1:   //  input_stream 적용
                        slide_show_B();
                        break ;
                    case 2:   //
                        slide_show_Random();
                        break ;
                    default:
                        break ;
                }
            }
        };
        IS_thread.start();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //      Data = textView.getText().toString();
        //      outState.putStringArrayList(KEY_DATA, Data); 임시
    }

    public void slide_show_A () {
        class Images {
            private final Uri uri;
            private final String name;
            private final int size;
            public Images(Uri uri, String name,
                          int size) {
                this.uri = uri;
                this.name = name;
                this.size = size;
            }
        }
        List<Images> ImagesList = new ArrayList<Images>();
        String[] projection = new String[] {
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.SIZE
        };
        Cursor cursor = getApplicationContext().getContentResolver().query (
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projection , null , null, null
        );

        Log.d("============", "cursor.getCount() = " + cursor.getCount());
        if (cursor == null || !cursor.moveToFirst() || cursor.getCount() == 0 )  {
            Log.e("TAG", "cursor null or cursor is empty");
            return;
        }

        {
            int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
            int nameColumn =
                    cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
            int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
            while (cursor.moveToNext()) {
                final String name = cursor.getString(nameColumn);
                int size = cursor.getInt(sizeColumn);
                long id = cursor.getLong(idColumn);
                final Uri contentUri = ContentUris.withAppendedId(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
                ImagesList.add(new Images(contentUri, name, size));
                try {
                    int image_src = 2 ;
                    switch  ( image_src ) {
                        case 1:   //  그림의 가로 세로 방향이 뒤바뀌는 경우가 있슴
                            bitmap = getBitmapFromUri(contentUri) ;
                            break ;
                        case 2:   //  정상작동 확인
                            bitmap = getApplicationContext().getContentResolver().loadThumbnail(
                                    contentUri, new Size(640, 480), null);
                            break ;
                        default:
                            break ;
                    }
                    Thread slide_show_sub_thread = new Thread( ) {
                        @Override
                        public void run() {
                            runOnUiThread(new Runnable() {
                                @SuppressLint("WrongViewCast")
                                @Override
                                public void run() {
                                    setContentView(R.layout.activity_main);
                                    ImageView imageView = (ImageView) findViewById(R.id.imageView) ;
                                    imageView.setImageBitmap  (bitmap);
                                }
                            }) ;  }};
                    slide_show_sub_thread.start();
                    try {
                        sleep(1000);   // 보여주기 간격 1초 ( 1000 밀리초 )
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }

//  ************************************************************************
    public void slide_show_B () {

        Uri externalUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String[] projection = new String[]{
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.MIME_TYPE
        };
        Cursor cursor = getContentResolver().query(externalUri, projection, null, null, null);
        int name_int = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
        if (cursor == null || !cursor.moveToFirst()) {
            Log.e("TAG", "cursor null or cursor is empty");
            return;
        }
        do {
            final String contentUrl = externalUri.toString() + "/" + cursor.getString(0);
            final String name = cursor.getString(name_int) ;
            try {
                InputStream is = getContentResolver().openInputStream(Uri.parse(contentUrl));
                final String TAG = "slide_show_B: ";
                final Bitmap bitmap = BitmapFactory.decodeStream(is);
                is.close();
                if ( bitmap == null ) {
                    Log.d(TAG, "Error , bitmap == null ");
                } else {
                    Thread slide_showB_sub_thread = new Thread() {
                        @Override
                        public void run() {
                            runOnUiThread(new Runnable() {
                                @SuppressLint("WrongViewCast")
                                @Override
                                public void run() {
                                    setContentView(R.layout.activity_main);
                                    ImageView imageView = (ImageView) findViewById(R.id.imageView) ;
                                    imageView.setImageBitmap  (bitmap);
                                }
                            }) ;  }};
                    slide_showB_sub_thread.start();
                }
                Thread.sleep(1000);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (cursor.moveToNext());
    }

//  ************************************************************************
    public void slide_show_Random () {
        String TAG = "●●●●  slide_show_Random  : ";
        Log.d(TAG, "개시");


        class Images {
            private final Uri uri;
            private final String name;
            private final int size;
            public Images(Uri uri, String name,
                          int size) {
                this.uri = uri;
                this.name = name;
                this.size = size;
            }
        }
        String[] projection = new String[] {
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.SIZE
        };
        Cursor cursorR = getApplicationContext().getContentResolver().query (
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projection , null , null, null
        );
        int max_PICs = cursorR.getCount() - 1;
        Log.d(TAG, "cursor.getCount() = " + cursorR.getCount());
        if (cursorR == null || !cursorR.moveToFirst() || max_PICs == 0 )  {
            Log.e("TAG", "cursor null or cursor is empty");
            return;
        }

        List uri_array = new ArrayList();
        {
            int idColumn = cursorR.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
            int list_index = 0 ;
            while (cursorR.moveToNext()) {
                long id = cursorR.getLong(idColumn);
                final Uri contentUri = ContentUris.withAppendedId(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
                uri_array.add(list_index, contentUri);
            }
            ;
        };
        Uri contentUri = null;
        for ( ;; ){
            int list_index = 0 ;
            list_index = (int) (( Math.random() * max_PICs ) * 1);
            contentUri = (Uri) uri_array.get(list_index);
            try {
                bitmap = getApplicationContext().getContentResolver().loadThumbnail(
                         contentUri, new Size(640, 480), null);
                Thread slide_show_sub_thread = new Thread( ) {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @SuppressLint("WrongViewCast")
                            @Override
                            public void run() {
                                setContentView(R.layout.activity_main);
                                ImageView imageView = (ImageView) findViewById(R.id.imageView) ;
                                imageView.setImageBitmap  (bitmap);
                            }
                        }) ;  }};
                slide_show_sub_thread.start();
                try {
                    sleep(1000);   // 보여주기 간격 1초 ( 1000 밀리초 )
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }   //  for
    }  //


    private void checkPermissions() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(MainActivity.this,
                    "앱 시작전에 먼저, 저장장치 읽기 권한을 주세요", Toast.LENGTH_LONG).show();
            finish();
        }
    };
};

AllPictures.zip
0.14MB

 

manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.allpictures">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="몽땅_쑈"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

activity_mail.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=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#000000"
        android:backgroundTint="#000000"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_launcher_background" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

styles.xml

<resources>
    <!-- Base application theme. -->
    <!-- https://docs.microsoft.com/ko-kr/xamarin/android/user-interface/material-theme -->
    <style name="AppTheme" parent="Theme.AppCompat">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimaryDark</item>
        <item name="colorPrimaryDark">#000000</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:navigationBarColor">#000000</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
</resources>

 

Posted by LODE_RUNNER
,

String TAG = "dirs : ";
Log.d(TAG + "getRootDirectory()", getRootDirectory().toString());
Log.d(TAG + "getExternalMediaDirs()", getExternalMediaDirs().toString());
Log.d(TAG + "getExternalFilesDir()", getExternalFilesDir(null).toString());
Log.d(TAG + "getExternalFilesDirs()", getExternalFilesDirs(null).toString());
Log.d(TAG + "getFilesDir()", getFilesDir().toString());
Log.d(TAG + "getExternalCacheDir()", getExternalCacheDir().toString());
Log.d(TAG + "getExternalCacheDirs()", getExternalCacheDirs().toString());

Log.d(TAG + "getDataDirectory()" , getDataDirectory().toString());
Log.d(TAG + "getDataDir()", getDataDir().toString());
Log.d(TAG + "getCacheDir()", getCacheDir().toString());
Log.d(TAG + "getPackageResourcePath()", getPackageResourcePath().toString());
Log.d(TAG + "getDatabasePath()" , getDatabasePath(null).toString());

Posted by LODE_RUNNER
,

IMage Application.zip
0.15MB

티스토리 가입 기념 , 첫 포스팅

 

ㅡ 안드로이드/자바에서 이미지 표시하기

ㅡ 요점은 이미지 뷰 사용법이 아니라,

ㅡ 이미지 파일들을 인텐트로 요청하고 받아서

ㅡ 받은 url 정보를 해석하여

ㅡ 비트맵으로 변환하는 과정

 

ㅡ 이러한 해설은, 안드로이드 매뉴얼의 이미지 단원이나 인텐트 단원에 있지 않고

ㅡ "콘텐트 프로바이더 / 저장소 액세스 프레임워크를 사용하여 파일 열기" 해설 부분(링크)에 있슴

ㅡ 초심자가 여기까지 독학으로 오려면 몇달 걸리게 됨

 

ㅡ 소스 해설 생략  /  링크에 안내된 해설 참조 /  첨부 파일을 통째로 실행해 보세요

 

 

요점 :https://developer.android.com/guide/topics/providers/document-provider

 

 

MainActivity.java
//   MainActivity.java
//
package com.example.imageapplication;

//  import 생략

public class MainActivity extends AppCompatActivity {
    private static final int GPS_ENABLE_REQUEST_CODE = 2001;
    private static final int REQUEST_IMAGE_CAPTURE = 1 ;
    private static final int PERMISSIONS_REQUEST_CODE = 100;
    private static final int PICK_FROM_CAMERA = 0;
    private static final int PICK_FROM_ALBUM = 1;
    private static final int CROP_FROM_CAMERA = 2;
    private static final int GET_GALLERY_IMAGE = 200;
    private static final int REQUEST_TAKE_ALBUM = 103 ;
    private static final int  READ_REQUEST_CODE = 42;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .permitDiskReads()
                .permitDiskWrites()
                .permitNetwork().build());

        TextView textView = (TextView) findViewById(R.id.textView);
        textView.setText("******** 이미지 데모 ********\n");

        Button ButtonR = (Button) findViewById(R.id.ButtonR);
        Button ButtonL = (Button) findViewById(R.id.ButtonL);

// *******************************************************************************
//   https://developer.android.com/guide/topics/providers/document-provider
        ButtonL.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                final CharSequence[] SysSetUpItems =
                        {       "0 : image binary 보내기",
                                "1 : ACTION_GET_CONTENT 가져오기",
                                "2 : ACTION_OPEN_DOCUMENT 가져오기" } ;
                AlertDialog.Builder SysSetUpDialog = new AlertDialog.Builder(MainActivity.this,
                        android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
                SysSetUpDialog.setTitle("다음 중 선택하세요")
                        .setItems(SysSetUpItems, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                switch (which) {
                                    case 0: //  이미지 데이타 등 바이너리 콘텐츠 보내기
                                        String uriToImage = null;
                                        Intent shareIntent2 = new Intent();
                                        shareIntent2.setAction(Intent.ACTION_SEND);
                                        shareIntent2.putExtra(Intent.EXTRA_STREAM, uriToImage);
                                        shareIntent2.setType("image/jpeg");
                                        startActivity(Intent.createChooser(shareIntent2, "abcd"));
                                        break;

                                    case 1: //
                                        // READ_REQUEST_CODE = 42;
                                        Intent intent1 = new Intent(Intent.ACTION_GET_CONTENT);
                                        intent1.addCategory(Intent.CATEGORY_OPENABLE);
                                        intent1.setType("image/*");
                                        startActivityForResult(intent1, 42);  // READ_REQUEST_CODE
                                        break;
                                    case 2: //
                                        // READ_REQUEST_CODE = 42;
                                        Intent intent2 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                                        intent2.addCategory(Intent.CATEGORY_OPENABLE);
                                        intent2.setType("image/*");
                                        startActivityForResult(intent2, 42);  // READ_REQUEST_CODE
                                        break;
                                   default:
                                        break;
                                }
                            }
                        })
                        .setCancelable(true)
                        .show();
            }
        });
// *******************************************************************************
        ButtonR.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                final CharSequence[] SysSetUpItems = {"0","1", "2",    "3","4","5" } ;
                AlertDialog.Builder SysSetUpDialog = new AlertDialog.Builder(MainActivity.this,
                        android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
                SysSetUpDialog.setTitle("다음 중 선택하세요")
                        .setItems(SysSetUpItems, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                switch (which) {
                                    case 0: //  System.exit(0)
                                        Intent intent0 = new Intent();
                                        intent0 = new Intent(Intent.ACTION_PICK);
                                        intent0.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
                                        startActivityForResult(intent0, 1);
                                        break;
                                    case 1:
                                        Intent intent1 = new Intent();
                                        intent1.setAction(Intent.ACTION_PICK);
                                        intent1.setType("image/*");
                                        startActivityForResult(intent1, 1);
                                        break;
                                    case 2:
                                        Intent intent2 = new Intent();
                                        intent2.setAction(Intent.ACTION_GET_CONTENT);
                                        intent2.setType("image/*");
                                        startActivityForResult(intent2, 1);
                                        break;
                                    case 3:
                                        Intent intent3 = new Intent();
                                        intent3.setAction(Intent.ACTION_GET_CONTENT);
                                        intent3.setType(android.provider.MediaStore.Images.Media.CONTENT_TYPE);
                                        startActivityForResult(intent3, 1);
                                        break;
                                    case 4:
                                        Intent intent4 = new Intent(Intent.ACTION_PICK);
                                        intent4. setDataAndType(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
                                        startActivityForResult(intent4, GET_GALLERY_IMAGE);  // 200
                                        break;
                                    case 5:
                                        Intent intent5 = new Intent();
                                        intent5.setAction(Intent.ACTION_GET_CONTENT); // ACTION_PICK은 사용하지 말것, deprecated + formally
                                        intent5.setType("image/*");
                                        ((Activity)MainActivity.this).startActivityForResult(Intent.createChooser(intent5, "Get Album"), REQUEST_TAKE_ALBUM);
                                        break;
                                    default:
                                        break;
                                }
                            }
                        })
                        .setCancelable(true)
                        .show();
            }
        });
    }
// **********************************************
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// **********************************************
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
//        Intent intent = getIntent();
//        Uri data = intent.getData();
        Log.d(" onActivityResult ", " requestCode: " + requestCode);
        switch (requestCode) {
            case 42 :   //  READ_REQUEST_CODE
                Uri uri = null;
                if (data != null) {
                    uri = data.getData();
                    Log.i("********* Image Test ********* ", "Uri: " + uri.toString());
                    try {
                        showImage(uri);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                };
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + requestCode);
        }
    } ;
    public void          showImage(final Uri uri) throws IOException {
        Thread bm_thread = new Thread() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @SuppressLint("WrongViewCast")
                    @Override
                    public void run() {
                        try {
                            Bitmap bm = getBitmapFromUri(uri) ;
                            ImageView imageView = (ImageView) findViewById(R.id.imageView) ;
                            imageView.setImageBitmap  (bm);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
        }) ;  }};
        bm_thread.start();
    }

    public Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }
}

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=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/ButtonL"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/ButtonL"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ButtonL"
        app:layout_constraintBottom_toTopOf="@+id/textView"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/ButtonR"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ButtonR"
        app:layout_constraintBottom_toBottomOf="@+id/ButtonL"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/ButtonL"
        app:layout_constraintVertical_bias="0.0" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="fill_parent"
        android:layout_height="200dp"
        android:layout_weight="1.0"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

manifest

 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.imageapplication">

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GPS_ENABLE_REQUEST_CODE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.FLAG_GRANT_READ_URI_PERMISSION"/>
    <uses-permission android:name="android.permission.FLAG_GRANT_WRITE_URI_PERMISSION"/>
    <uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action
                    android:name="android.intent.action.PICK"/>
                <category
                    android:name="android.intent.category.DEFAULT"/>
                <category
                    android:name="android.intent.category.OPENABLE"/>
                <data android:mimeType="text/plain"/>
                <data android:mimeType="image/*"/>
            </intent-filter>

            <intent-filter>
                <action android:name="android.media.action.IMAGE_CAPTURE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />
                <!-- <data android:type="image/*" />  -->
                <category android:name="android.intent.category.DEFAULT" />
                <!-- The OPENABLE category declares that the returned file is accessible
                     from a content provider that supports OpenableColumns
                     and ContentResolver.openFileDescriptor() -->
                <category android:name="android.intent.category.OPENABLE" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
            </intent-filter>

        </activity>
    </application>

</manifest>

 

기타1

webnautes.tistory.com

 

 

기타2

developer.android.com/reference/android/os/AsyncTask

 

 

기타3

developer.android.com/training/data-storage/files/external-scoped?hl=ko#java

 

 

기타4

g-y-e-o-m.tistory.com/107

 

 

////

 

Posted by LODE_RUNNER
,