Kujutiste suuruse muutmine üleslaadimise / allalaadimise paremaks muutmiseks. Androidi arendus.

Pole eriti tavaline näha projekti, mis ei nõua ühel või teisel kujul fotode üleslaadimist. Enamik nutitelefoni nutiseadmeid loob tänapäeval foto, mille suurus on 2 MB. See on probleem, kuidas? Kujutage ette, et loote mobiilirakenduse, mis nõuab teie kasutajatelt profiilipildi olemasolu, pidades silmas mastaapsust, iga foto ei tohi olla suurem kui 100KB, eks? Te ei soovi iga kasutaja jaoks 1 MB foto salvestada. See ei mõjuta ainult teie UX-i, vaid kannatab ka teie server. Suure foto üleslaadimine serverisse võib põhjustada ühe või kõik järgmised probleemid

  • Aeglane üles- ja allalaadimistoiming madala võrgu ribalaiusega seadmetes
  • Mõjuta toote mastaapsust
  • Ja veel…

LAHUS

Tegelik ilmselge lahendus on foto suuruse muutmine enne serverisse saatmist. Tore !. Aga kuidas? See on see, mida ma üritan näidata.

Mul oli vähe probleeme nuputades, kuidas seda lahendada, kui hakkasin androidi jaoks rakendusi kirjutama, nii et otsustasin seda täna lihtsalt jagada. Ootan huviga kedagi, kes näitaks mulle paremat viisi, kuidas seda teha. Lähme!

Eeldus

  • Ma eeldan, et Java-programmeerimiskeelega on teil mugav (see, mida ma kasutan, saate sellest hõlpsalt haarata, kui teil on kogemusi ka teiste programmeerimiskeeltega.)
  • Androidi stuudio ja SDK on installitud ja valmis.
  • Looge uus android-stuudioprojekt. Ma kutsun minu EasyPhotoUpload

Projekti nimi - EasyPhotoUpload

Minimaalne SDK - 4.0.3, API 15

Põhimõtteliselt proovime

  • Laske kasutajal galeriist foto valida
  • Hankige valitud fototee
  • Valitud foto suuruse muutmine taustalõngal ja tulemuse tagastamine põhilõimele - nagu näete, on pildi suuruse muutmine kallis toiming ja seda ei tohi põhilõngal teha.

Selle artikli lõplik kood on saadaval saidil github - https://github.com/adigunhammedolalekan/easyphotoupload

Kui android-stuudio on projekti ehitamise lõpetanud ja olete kõik valmis, looge need paketid - tuum, kuulajad, tööriistad

Uue paketi all looge uus klass Util.java, järgmine on faili sisu.

'Avaliku klassi Util {

// SDF, et luua tihendatud failile ainulaadne nimi.
 avalik staatiline lõplik SimpleDateFormat SDF = uus SimpleDateFormat (“yyyymmddhhmmss”, Locale.getDefault ());

/ *
 tihendage fail / foto saidilt @param tee aktiivse seadme privaatsesse kohta ja tagastage tihendatud fail.
 @param path = Algne pilditee
 @param context = praegune android-kontekst
 * /
 avalik staatiline fail getCompressed (konteksti kontekst, stringitee) viskab IOExceptioni {

if (context == null)
 viska uus NullPointerException (“Kontekst ei tohi olla tühine.”);
 // seadme välise vahemälu kataloogi hankimine, võib-olla mõnes seadmes see pole saadaval,
 // seega langeb meie kood tagasi sisemise salvestuse vahemälu kataloogi, mis on alati saadaval, kuid väiksemas koguses
 Fail cacheDir = context.getExternalCacheDir ();
 if (cacheDir == null)
 // kukkuda tagasi
 cacheDir = context.getCacheDir ();

String rootDir = cacheDir.getAbsolutePath () + “/ ImageCompressor”;
 Faili juur = uus fail (rootDir);

// Looge ImageCompressori kaust, kui see juba puudub.
 if (! root.exists ())
 juur.mkdirs ();

// dekodeerida ja muuta algse bitikaardi suurust saidilt @param.
 Bitmap bitmap = decodeImageFromFiles (tee, / * soovitud laius * / 300, / * soovitud kõrgus * / 300);

// tihendatud pildifaili kohatäite loomine
 Tihendatud fail = uus fail (juur, SDF.vorming (uus kuupäev ()) + “.jpg” / * Teie soovitud vorming * /);

// teisendage dekodeeritud bitikaart voogesitamiseks
 ByteArrayOutputStream byteArrayOutputStream = uus ByteArrayOutputStream ();

/ * tihendage bitmap kaardiks byteArrayOutputStream
 Bitmap.compress (vorming, kvaliteet, OutputStream)

Kvaliteet on vahemikus 1–100.
 * /
 bitmap.compress (Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream);

/ *
 Praegu on meie bitmap objekt byteArrayOutputStream Object, kõik, mida järgmiseks vajame, on kirjutada see varem loodud tihendatud faili,
 java.io.FileOutputStream aitab meil just seda teha!

* /
 FileOutputStream fileOutputStream = uus FileOutputStream (tihendatud);
 fileOutputStream.write (byteArrayOutputStream.toByteArray ());
 fileOutputStream.flush ();

fileOutputStream.close ();

// Fail kirjutatud, naasege helistaja juurde. Valmis!
 naaske kokkusurutud;
 }

avalik staatiline bitmap decodeImageFromFiles (stringi tee, int laius, int kõrgus) {
 BitmapFactory.Options scaleOptions = uus BitmapFactory.Options ();
 scaleOptions.inJustDecodeBounds = true;
 BitmapFactory.decodeFile (tee, skaalavalikud);
 int skaala = 1;
 while (scaleOptions.outWidth / scale / 2> = laius
 && scaleOptions.outHeight / scale / 2> = kõrgus) {
 skaala * = 2;
 }
 // dekodeeri valimi suurusega
 BitmapFactory.Options outOptions = uus BitmapFactory.Options ();
 outOptions.inSampleSize = skaala;
 tagastama BitmapFactory.decodeFile (tee, outOptions);
 }
} ”

Foto tihendamise ja talletamise meetodiks on „staatiline faili saamise tihendamine (kontekst, string)”, nagu näete ülaltoodud koodist, see meetod kulgeb teel seadmes oleva foto juurde, muutke selle suurust, talletage see privaatses asukohas seadmes ja tagastab värskelt tihendatud faili. Voila!

Järgmine uuritav fail kannab nime ImageCompressTask.java, see klass rakendab käitatava kolme argumendiga konstruktoriga ja selle käivitusmeetodi korral toimub tihendamine kõik taustalõimega, see postitab lõpptulemuse peamisse niidi abil android.os.Handler või teatage veast muul viisil.

ImageCompressTask.java

„Avaliku klassi ImageCompressTask rakendab käivitatava {

privaatne kontekst mContext;
 privaatne loend originalPaths = new ArrayList <> ();
 private handler mHandler = uus käitleja (Looper.getMainLooper ());
 privaatne loend tulemus = uus ArrayList <> ();
 privaatne IImageCompressTaskListener mIImageCompressTaskListener;

avalik ImageCompressTask (konteksti kontekst, stringi tee, IImageCompressTaskListener compressTaskListener) {

originalPaths.add (tee);
 mContext = kontekst;

mIImageCompressTaskListener = compressTaskListener;
 }
 avalik ImageCompressTask (konteksti kontekst, loendi teed, IImageCompressTaskListener compressTaskListener) {
 originalPaths = teed;
 mContext = kontekst;
 mIImageCompressTaskListener = compressTaskListener;
 }
 @Ülesõit
 avalik tühine käitamine () {

proovige {

// Sirvige kõiki antud teid ja koguge tihendatud fail Util.getCompressed (kontekst, string)
 jaoks (String path: originalPaths) {
 Failifail = Util.getCompressed (mContext, tee);
 // lisa see!
 tulemus.add (fail);
 }
 // kasutage Handlerit, et tulemus tagasi peamisse lõime postitada
 mHandler.post (uus käivitatav () {
 @Ülesõit
 avalik tühine käitamine () {

if (mIImageCompressTaskListener! = null)
 mIImageCompressTaskListener.onComplete (tulemus);
 }
 });
 } saak (lõplik IOException erand) {
 // Tekkis tõrge, teatage veast tagasihelistamise kaudu
 mHandler.post (uus käivitatav () {
 @Ülesõit
 avalik tühine käitamine () {
 if (mIImageCompressTaskListener! = null)
 mIImageCompressTaskListener.onError (ex);
 }
 });
 }
 }
} ”

Lõpuks looge MainActivity.java, UI kogu proovirakenduse jaoks.

MainActivity.java

'
avaliku klassi MainActivity laiendab AppCompatActivity {

Button selectImage;
 ImageView selectedImage;

privaatne staatiline lõplik int REQUEST_STORAGE_PERMISSION = 100;
 privaatne staatiline lõplik int REQUEST_PICK_PHOTO = 101;

// looge meie piltide tihendamise klassi üks lõimebassein.
 private ExecutorService mExecutorService = Executors.newFixedThreadPool (1);

privaatne ImageCompressTask imageCompressTask;

@Ülesõit
 kaitstud tühine onCreate (Bundle savedInstanceState) {
 super.onCreate (SaveInstanceState);
 setContentView (R.layout.activity_main);

selectedImage = (ImageView) findViewById (R.id.iv_selected_photo);
 selectImage = (Button) findViewById (R.id.btn_select_image);

selectImage.setOnClickListener (uus View.OnClickListener () {
 @Ülesõit
 avalik tühine onClicki kaudu (kuva vaade) {
 requestPermission ();
 }
 });
 }

tühine requestPermission () {

if (PackageManager.PERMISSION_GRANTED! =
 ContextCompat.checkSelfPermission (see, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
 if (ActivityCompat.shouldShowRequestPermissionRationale (see, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
 ActivityCompat.requestPermissions (see, uus string [] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
 REQUEST_STORAGE_PERMISSION);
 } veel {
 // Jah! Ma tahan, et mõlemad blokid teeksid sama asja, võite kirjutada oma loogika, kuid see töötab minu jaoks.
 ActivityCompat.requestPermissions (see, uus string [] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
 REQUEST_STORAGE_PERMISSION);
 }
 } veel {
 // Luba on antud, laseb fotot valida
Tahtluse kavatsus = uus kavatsus (Intent.ACTION_PICK);
intent.setAction (Intent.ACTION_GET_CONTENT);
intent.setType (“pilt / *”);
startActivityForResult (kavatsus, REQUEST_PICK_PHOTO);
 }

}

@Ülesõit
 kaitstud tühine onActivityResult (int requestCode, int tulemusCode, kavatsuse andmed) {
 super.onActivityResult (requestCode, resultCode, data);
 if (requestCode == REQUEST_PICK_PHOTO && resultCode == RESULT_OK &&
 andmed! = null) {
 // eralda Uri-st absoluutse pildi tee
 Uri uri = data.getData ();
 Kursori kursor = MediaStore.Images.Media.query (getContentResolver (), uri, uus string [] {MediaStore.Images.Media.DATA});
 if (kursor! = null) {
 Stringi tee = cursor.getString (cursor.getColumnIndexOrThrow (MediaStore.Images.Media.DATA));

// Looge ImageCompressTask ja käivitage koos käivitajaga.
 imageCompressTask = uus ImageCompressTask (see, tee, iImageCompressTaskListener);

mExecutorService.execute (imageCompressTask);
 }
 }
 }

// pildi tihendamise ülesande tagasihelistamine
 privaatne IImageCompressTaskListener iImageCompressTaskListener = uus IImageCompressTaskListener () {
 @Ülesõit
 avalik tühine onComplete (nimekiri tihendatud) {
 // foto tihendatud. Jah!

// valmistuge üleslaadimiseks.

Failifail = tihendatud.get (0);

selectedImage.setImageBitmap (BitmapFactory.decodeFile (file.getAbsolutePath ()));
 }

@Ülesõit
 public void onError (korduv viga) {
 // väga ebatõenäoline, kuid see võib juhtuda äärmiselt vähese mälumahuga seadmes.
 // logige sisse, log.WhatTheFuck? või näidake dialoogi, kus kasutajal palutakse kustutada mõned failid ... jne
 Log.wtf (“ImageCompressor”, “Ilmnes viga”, tõrge);
 }
 };

@Ülesõit
 kaitstud tühine onDestroy () {
 super.onDestroy ();

//korista ära!
 mExecutorService.shutdown ();

mExecutorService = null;
 imageCompressTask = null;
 }
} ”

Kõiki koode kommenteeritakse hästi, kuid kui teil on mõne osaga probleeme. Andke mulle teada! Kõik koodid asuvad githubis, parema ülevaate saamiseks külastage seda. Ekraanipilt lõpptulemusest.

Armastan teie panust selles. Aitäh!

Minust

Olen kirglik mobiilirakenduste arendaja, kellel on vähemalt 2,5-aastane kogemus Androidi platvormile suurepäraste rakenduste loomisega. Kui teil on vaja minu annet, võtke minuga julgelt ühendust!

Github - www.github.com/adigunhammedolalekan

Post - adigunhammed.lekan@gmail.com

Kontakt - 07035452307