19f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/* 2f04335f899f2cce69f843692a3cb9cec229683c2tturney * Copyright (C) 2017 The Android Open Source Project 39f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 4f04335f899f2cce69f843692a3cb9cec229683c2tturney * Licensed under the Apache License, Version 2.0 (the "License"); 5f04335f899f2cce69f843692a3cb9cec229683c2tturney * you may not use this file except in compliance with the License. 6f04335f899f2cce69f843692a3cb9cec229683c2tturney * You may obtain a copy of the License at 79f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 8f04335f899f2cce69f843692a3cb9cec229683c2tturney * http://www.apache.org/licenses/LICENSE-2.0 99f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Unless required by applicable law or agreed to in writing, software 11f04335f899f2cce69f843692a3cb9cec229683c2tturney * distributed under the License is distributed on an "AS IS" BASIS, 12f04335f899f2cce69f843692a3cb9cec229683c2tturney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f04335f899f2cce69f843692a3cb9cec229683c2tturney * See the License for the specific language governing permissions and 14f04335f899f2cce69f843692a3cb9cec229683c2tturney * limitations under the License. 159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage com.googlecode.android_scripting; 189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.app.AlertDialog; 209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.app.ProgressDialog; 219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.Context; 229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.DialogInterface; 239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.content.DialogInterface.OnCancelListener; 249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport android.os.AsyncTask; 259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.exception.Sl4aException; 279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport com.googlecode.android_scripting.future.FutureResult; 289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.File; 309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.FileNotFoundException; 319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.FileOutputStream; 329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.IOException; 339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.Enumeration; 349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.zip.ZipEntry; 359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.zip.ZipFile; 369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/** 389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * AsyncTask for extracting ZIP files. 399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * 409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */ 419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class ZipExtractorTask extends AsyncTask<Void, Integer, Long> { 429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private static enum Replace { 449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li YES, NO, YESTOALL, SKIPALL 459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final File mInput; 489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final File mOutput; 499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final ProgressDialog mDialog; 509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Throwable mException; 519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private int mProgress = 0; 529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final Context mContext; 539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private boolean mReplaceAll; 549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private final class ProgressReportingOutputStream extends FileOutputStream { 569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private ProgressReportingOutputStream(File f) throws FileNotFoundException { 579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(f); 589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void write(byte[] buffer, int offset, int count) throws IOException { 629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super.write(buffer, offset, count); 639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mProgress += count; 649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li publishProgress(mProgress); 659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public ZipExtractorTask(String in, String out, Context context, boolean replaceAll) 699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throws Sl4aException { 709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li super(); 719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInput = new File(in); 729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mOutput = new File(out); 739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!mOutput.exists()) { 749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!mOutput.mkdirs()) { 759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li throw new Sl4aException("Failed to make directories: " + mOutput.getAbsolutePath()); 769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (context != null) { 799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog = new ProgressDialog(context); 809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog = null; 829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mContext = context; 859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mReplaceAll = replaceAll; 869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected void onPreExecute() { 919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.v("Extracting " + mInput.getAbsolutePath() + " to " + mOutput.getAbsolutePath()); 929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDialog != null) { 939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setTitle("Extracting"); 949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setMessage(mInput.getName()); 959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setOnCancelListener(new OnCancelListener() { 979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onCancel(DialogInterface dialog) { 999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li cancel(true); 1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.show(); 1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected Long doInBackground(Void... params) { 1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return unzip(); 1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (Exception e) { 1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mInput.exists()) { 1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Clean up bad zip file. 1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mInput.delete(); 1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mException = e; 1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected void onProgressUpdate(Integer... progress) { 1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDialog == null) { 1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (progress.length > 1) { 1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li int max = progress[1]; 1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setMax(max); 1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } else { 1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setProgress(progress[0].intValue()); 1309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected void onPostExecute(Long result) { 1359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDialog != null && mDialog.isShowing()) { 1369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.dismiss(); 1379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (isCancelled()) { 1399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return; 1409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mException != null) { 1429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e("Zip extraction failed.", mException); 1439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 1479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li protected void onCancelled() { 1489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (mDialog != null) { 1499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mDialog.setTitle("Extraction cancelled."); 1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private long unzip() throws Exception { 1549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li long extractedSize = 0l; 1559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Enumeration<? extends ZipEntry> entries; 1569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ZipFile zip = new ZipFile(mInput); 1579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li long uncompressedSize = getOriginalSize(zip); 1589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li publishProgress(0, (int) uncompressedSize); 1609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li entries = zip.entries(); 1629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 1639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 1649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li while (entries.hasMoreElements()) { 1659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ZipEntry entry = entries.nextElement(); 1669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (entry.isDirectory()) { 1679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // Not all zip files actually include separate directory entries. 1689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // We'll just ignore them 1699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // and create them as necessary for each actual entry. 1709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li continue; 1719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li File destination = new File(mOutput, entry.getName()); 1739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (!destination.getParentFile().exists()) { 1749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li destination.getParentFile().mkdirs(); 1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (destination.exists() && mContext != null && !mReplaceAll) { 1779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Replace answer = showDialog(entry.getName()); 1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li switch (answer) { 1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case YES: 1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li break; 1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case NO: 1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li continue; 1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case YESTOALL: 1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mReplaceAll = true; 1859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li break; 1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li default: 1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return extractedSize; 1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ProgressReportingOutputStream outStream = new ProgressReportingOutputStream(destination); 1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li extractedSize += IoUtils.copy(zip.getInputStream(entry), outStream); 1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li outStream.close(); 1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } finally { 1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li zip.close(); 1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (Exception e) { 1989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li // swallow this exception, we are only interested in the original one 1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.v("Extraction is complete."); 2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return extractedSize; 2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private long getOriginalSize(ZipFile file) { 2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Enumeration<? extends ZipEntry> entries = file.entries(); 2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li long originalSize = 0l; 2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li while (entries.hasMoreElements()) { 2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li ZipEntry entry = entries.nextElement(); 2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li if (entry.getSize() >= 0) { 2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li originalSize += entry.getSize(); 2129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return originalSize; 2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li private Replace showDialog(final String name) { 2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li final FutureResult<Replace> mResult = new FutureResult<Replace>(); 2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li MainThread.run(mContext, new Runnable() { 2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void run() { 2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setTitle(String.format("Script \"%s\" already exist.", name)); 2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setMessage(String.format("Do you want to replace script \"%s\" ?", name)); 2269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li DialogInterface.OnClickListener buttonListener = new DialogInterface.OnClickListener() { 2289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onClick(DialogInterface dialog, int which) { 2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Replace result = Replace.SKIPALL; 2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li switch (which) { 2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case DialogInterface.BUTTON_POSITIVE: 2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result = Replace.YES; 2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li break; 2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case DialogInterface.BUTTON_NEGATIVE: 2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result = Replace.NO; 2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li break; 2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li case DialogInterface.BUTTON_NEUTRAL: 2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li result = Replace.YESTOALL; 2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li break; 2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mResult.set(result); 2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li dialog.dismiss(); 2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }; 2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setNegativeButton("Skip", buttonListener); 2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setPositiveButton("Replace", buttonListener); 2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setNeutralButton("Replace All", buttonListener); 2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.setOnCancelListener(new DialogInterface.OnCancelListener() { 2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li @Override 2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li public void onCancel(DialogInterface dialog) { 2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li mResult.set(Replace.SKIPALL); 2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li dialog.dismiss(); 2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li builder.show(); 2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li }); 2609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li 2619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li try { 2629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return mResult.get(); 2639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } catch (InterruptedException e) { 2649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li Log.e(e); 2659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li return null; 2679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li } 2689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li} 269