Loading packages/SystemUI/res/layout/global_screenshot.xml +1 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ android:id="@+id/global_screenshot_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/global_screenshot_background" android:visibility="gone"> <ImageView android:id="@+id/global_screenshot" Loading @@ -32,9 +33,4 @@ android:layout_height="wrap_content" android:adjustViewBounds="true" /> </FrameLayout> <ImageView android:id="@+id/global_screenshot_flash" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFFFF" android:visibility="gone" /> </FrameLayout> packages/SystemUI/res/values/strings.xml +14 −4 Original line number Diff line number Diff line Loading @@ -168,10 +168,20 @@ <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] --> <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string> <!-- toast message displayed when a screenshot is saved to the Gallery. --> <string name="screenshot_saving_toast">Screenshot saved to Gallery</string> <!-- toast message displayed when we fail to take a screenshot. --> <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string> <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] --> <string name="screenshot_saving_ticker">Saving...</string> <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] --> <string name="screenshot_saving_title">Saving screenshot...</string> <!-- Notification text displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=100] --> <string name="screenshot_saving_text">Please wait for screenshot to be saved</string> <!-- Notification title displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=50] --> <string name="screenshot_saved_title">Screenshot captured</string> <!-- Notification text displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=100] --> <string name="screenshot_saved_text">Touch to view your screenshot</string> <!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] --> <string name="screenshot_failed_title">Screenshot failed</string> <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] --> <string name="screenshot_failed_text">Failed to save screenshot. External storage may be in use.</string> <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] --> <string name="usb_preference_title">USB file transfer options</string> Loading packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +111 −50 Original line number Diff line number Diff line Loading @@ -19,27 +19,27 @@ package com.android.systemui.screenshot; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; import android.os.Environment; import android.os.ServiceManager; import android.provider.MediaStore; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.IWindowManager; import android.view.LayoutInflater; Loading @@ -50,16 +50,11 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.android.systemui.R; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.Thread; import java.text.SimpleDateFormat; import java.util.Date; Loading @@ -83,6 +78,46 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s"; private int mNotificationId; private NotificationManager mNotificationManager; private Notification.Builder mNotificationBuilder; private Intent mLaunchIntent; private String mImageDir; private String mImageFileName; private String mImageFilePath; private String mImageDate; private long mImageTime; SaveImageInBackgroundTask(Context context, NotificationManager nManager, int nId) { Resources r = context.getResources(); // Prepare all the output metadata mImageTime = System.currentTimeMillis(); mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime)); mImageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath(); mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate); mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir, SCREENSHOTS_DIR_NAME, mImageFileName); // Show the intermediate notification mLaunchIntent = new Intent(Intent.ACTION_VIEW); mLaunchIntent.setDataAndType(Uri.fromFile(new File(mImageFilePath)), "image/png"); mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mNotificationId = nId; mNotificationBuilder = new Notification.Builder(context) .setTicker(r.getString(R.string.screenshot_saving_ticker)) .setContentTitle(r.getString(R.string.screenshot_saving_title)) .setContentText(r.getString(R.string.screenshot_saving_text)) .setSmallIcon(android.R.drawable.ic_menu_gallery) .setWhen(System.currentTimeMillis()); Notification n = mNotificationBuilder.getNotification(); n.flags |= Notification.FLAG_NO_CLEAR; mNotificationManager = nManager; mNotificationManager.notify(nId, n); } @Override protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) { if (params.length != 1) return null; Loading @@ -91,23 +126,15 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi Bitmap image = params[0].image; try { long currentTime = System.currentTimeMillis(); String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(currentTime)); String imageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath(); String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date); String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir, SCREENSHOTS_DIR_NAME, imageFileName); // Save the screenshot to the MediaStore ContentValues values = new ContentValues(); ContentResolver resolver = context.getContentResolver(); values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath); values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName); values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName); values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime); values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath); values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName); values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName); values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime); values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime); values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime); values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png"); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Loading @@ -118,7 +145,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // update file size in the database values.clear(); values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length()); values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length()); resolver.update(uri, values, null, null); params[0].result = 0; Loading @@ -135,12 +162,22 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi protected void onPostExecute(SaveImageInBackgroundData params) { if (params.result > 0) { // Show a message that we've failed to save the image to disk Toast.makeText(params.context, R.string.screenshot_failed_toast, Toast.LENGTH_SHORT).show(); GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager); } else { // Show a message that we've saved the screenshot to disk Toast.makeText(params.context, R.string.screenshot_saving_toast, Toast.LENGTH_SHORT).show(); // Show the final notification to indicate screenshot saved Resources r = params.context.getResources(); mNotificationBuilder .setTicker(r.getString(R.string.screenshot_saved_title)) .setContentTitle(r.getString(R.string.screenshot_saved_title)) .setContentText(r.getString(R.string.screenshot_saved_text)) .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0)) .setWhen(System.currentTimeMillis()) .setAutoCancel(true); Notification n = mNotificationBuilder.getNotification(); n.flags &= ~Notification.FLAG_NO_CLEAR; mNotificationManager.notify(mNotificationId, n); } params.finisher.run(); }; Loading @@ -154,22 +191,21 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi */ class GlobalScreenshot { private static final String TAG = "GlobalScreenshot"; private static final int SCREENSHOT_FADE_IN_DURATION = 900; private static final int SCREENSHOT_NOTIFICATION_ID = 789; private static final int SCREENSHOT_FADE_IN_DURATION = 500; private static final int SCREENSHOT_FADE_OUT_DELAY = 1000; private static final int SCREENSHOT_FADE_OUT_DURATION = 450; private static final int TOAST_FADE_IN_DURATION = 500; private static final int TOAST_FADE_OUT_DELAY = 1000; private static final int TOAST_FADE_OUT_DURATION = 500; private static final int SCREENSHOT_FADE_OUT_DURATION = 300; private static final float BACKGROUND_ALPHA = 0.65f; private static final float SCREENSHOT_SCALE = 0.85f; private static final float SCREENSHOT_MIN_SCALE = 0.7f; private static final float SCREENSHOT_ROTATION = -6.75f; // -12.5f; private static final float SCREENSHOT_SCALE_FUDGE = 0.075f; // To account for the border padding private static final float SCREENSHOT_SCALE = 0.8f; private static final float SCREENSHOT_MIN_SCALE = 0.775f; private Context mContext; private LayoutInflater mLayoutInflater; private IWindowManager mIWindowManager; private WindowManager mWindowManager; private WindowManager.LayoutParams mWindowLayoutParams; private NotificationManager mNotificationManager; private Display mDisplay; private DisplayMetrics mDisplayMetrics; private Matrix mDisplayMatrix; Loading @@ -182,10 +218,15 @@ class GlobalScreenshot { private AnimatorSet mScreenshotAnimation; // General use cubic interpolator final TimeInterpolator mCubicInterpolator = new TimeInterpolator() { // Fade interpolators final TimeInterpolator mFadeInInterpolator = new TimeInterpolator() { public float getInterpolation(float t) { return t*t*t; return (float) Math.pow(t, 1.5f); } }; final TimeInterpolator mFadeOutInterpolator = new TimeInterpolator() { public float getInterpolation(float t) { return (float) t; } }; // The interpolator used to control the background alpha at the start of the animation Loading Loading @@ -237,6 +278,8 @@ class GlobalScreenshot { PixelFormat.TRANSLUCENT); mWindowLayoutParams.setTitle("ScreenshotAnimation"); mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); } Loading @@ -248,7 +291,8 @@ class GlobalScreenshot { data.context = mContext; data.image = mScreenBitmap; data.finisher = finisher; new SaveImageInBackgroundTask().execute(data); new SaveImageInBackgroundTask(mContext, mNotificationManager, SCREENSHOT_NOTIFICATION_ID) .execute(data); } /** Loading Loading @@ -300,8 +344,7 @@ class GlobalScreenshot { // If we couldn't take the screenshot, notify the user if (mScreenBitmap == null) { Toast.makeText(mContext, R.string.screenshot_failed_toast, Toast.LENGTH_SHORT).show(); notifyScreenshotError(mContext, mNotificationManager); finisher.run(); return; } Loading Loading @@ -341,12 +384,13 @@ class GlobalScreenshot { } private ValueAnimator createScreenshotFadeInAnimation() { ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setInterpolator(mCubicInterpolator); anim.setInterpolator(mFadeInInterpolator); anim.setDuration(SCREENSHOT_FADE_IN_DURATION); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { mBackgroundView.setVisibility(View.VISIBLE); mScreenshotContainerView.setTranslationY(0f); mScreenshotContainerView.setVisibility(View.VISIBLE); } }); Loading @@ -356,18 +400,19 @@ class GlobalScreenshot { float t = ((Float) animation.getAnimatedValue()).floatValue(); mBackgroundView.setAlpha(mBackgroundViewAlphaInterpolator.getInterpolation(t) * BACKGROUND_ALPHA); float scaleT = SCREENSHOT_SCALE + (1f - t) * SCREENSHOT_SCALE; float scaleT = SCREENSHOT_SCALE + (1f - t) * (1f - SCREENSHOT_SCALE) + SCREENSHOT_SCALE_FUDGE; mScreenshotContainerView.setAlpha(t*t*t*t); mScreenshotContainerView.setScaleX(scaleT); mScreenshotContainerView.setScaleY(scaleT); mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION); } }); return anim; } private ValueAnimator createScreenshotFadeOutAnimation() { ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f); anim.setInterpolator(mCubicInterpolator); anim.setInterpolator(mFadeOutInterpolator); anim.setStartDelay(SCREENSHOT_FADE_OUT_DELAY); anim.setDuration(SCREENSHOT_FADE_OUT_DURATION); anim.addListener(new AnimatorListenerAdapter() { Loading @@ -381,8 +426,9 @@ class GlobalScreenshot { @Override public void onAnimationUpdate(ValueAnimator animation) { float t = ((Float) animation.getAnimatedValue()).floatValue(); float scaleT = SCREENSHOT_MIN_SCALE + t*(SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE); float scaleT = SCREENSHOT_MIN_SCALE + t * (SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE) + SCREENSHOT_SCALE_FUDGE; mScreenshotContainerView.setAlpha(t); mScreenshotContainerView.setScaleX(scaleT); mScreenshotContainerView.setScaleY(scaleT); Loading @@ -391,4 +437,19 @@ class GlobalScreenshot { }); return anim; } static void notifyScreenshotError(Context context, NotificationManager nManager) { Resources r = context.getResources(); // Clear all existing notification, compose the new notification and show it Notification n = new Notification.Builder(context) .setTicker(r.getString(R.string.screenshot_failed_title)) .setContentTitle(r.getString(R.string.screenshot_failed_title)) .setContentText(r.getString(R.string.screenshot_failed_text)) .setSmallIcon(android.R.drawable.ic_menu_report_image) .setWhen(System.currentTimeMillis()) .setAutoCancel(true) .getNotification(); nManager.notify(SCREENSHOT_NOTIFICATION_ID, n); } } packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +0 −14 Original line number Diff line number Diff line Loading @@ -17,26 +17,12 @@ package com.android.systemui.screenshot; import android.app.Service; import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import com.android.internal.app.AlertActivity; import com.android.internal.app.AlertController; import com.android.systemui.R; public class TakeScreenshotService extends Service { private static final String TAG = "TakeScreenshotService"; Loading packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +22 −0 Original line number Diff line number Diff line Loading @@ -146,4 +146,26 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac mDoNotDisturb = new DoNotDisturb(mContext); } protected View updateNotificationVetoButton(View row, StatusBarNotification n) { View vetoButton = row.findViewById(R.id.veto); if (n.isClearable()) { final String _pkg = n.pkg; final String _tag = n.tag; final int _id = n.id; vetoButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { mBarService.onNotificationClear(_pkg, _tag, _id); } catch (RemoteException ex) { // system process is dead if we're here. } } }); vetoButton.setVisibility(View.VISIBLE); } else { vetoButton.setVisibility(View.GONE); } return vetoButton; } } Loading
packages/SystemUI/res/layout/global_screenshot.xml +1 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ android:id="@+id/global_screenshot_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/global_screenshot_background" android:visibility="gone"> <ImageView android:id="@+id/global_screenshot" Loading @@ -32,9 +33,4 @@ android:layout_height="wrap_content" android:adjustViewBounds="true" /> </FrameLayout> <ImageView android:id="@+id/global_screenshot_flash" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFFFF" android:visibility="gone" /> </FrameLayout>
packages/SystemUI/res/values/strings.xml +14 −4 Original line number Diff line number Diff line Loading @@ -168,10 +168,20 @@ <!-- Compatibility mode help screen: body text. [CHAR LIMIT=150] --> <string name="compat_mode_help_body">When an app was designed for a smaller screen, a zoom control will appear by the clock.</string> <!-- toast message displayed when a screenshot is saved to the Gallery. --> <string name="screenshot_saving_toast">Screenshot saved to Gallery</string> <!-- toast message displayed when we fail to take a screenshot. --> <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string> <!-- Notification ticker displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=30] --> <string name="screenshot_saving_ticker">Saving...</string> <!-- Notification title displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=50] --> <string name="screenshot_saving_title">Saving screenshot...</string> <!-- Notification text displayed when a screenshot is being saved to the Gallery. [CHAR LIMIT=100] --> <string name="screenshot_saving_text">Please wait for screenshot to be saved</string> <!-- Notification title displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=50] --> <string name="screenshot_saved_title">Screenshot captured</string> <!-- Notification text displayed when a screenshot is saved to the Gallery. [CHAR LIMIT=100] --> <string name="screenshot_saved_text">Touch to view your screenshot</string> <!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] --> <string name="screenshot_failed_title">Screenshot failed</string> <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] --> <string name="screenshot_failed_text">Failed to save screenshot. External storage may be in use.</string> <!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] --> <string name="usb_preference_title">USB file transfer options</string> Loading
packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +111 −50 Original line number Diff line number Diff line Loading @@ -19,27 +19,27 @@ package com.android.systemui.screenshot; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.media.MediaScannerConnection; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; import android.os.Environment; import android.os.ServiceManager; import android.provider.MediaStore; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.IWindowManager; import android.view.LayoutInflater; Loading @@ -50,16 +50,11 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.android.systemui.R; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.Thread; import java.text.SimpleDateFormat; import java.util.Date; Loading @@ -83,6 +78,46 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png"; private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s"; private int mNotificationId; private NotificationManager mNotificationManager; private Notification.Builder mNotificationBuilder; private Intent mLaunchIntent; private String mImageDir; private String mImageFileName; private String mImageFilePath; private String mImageDate; private long mImageTime; SaveImageInBackgroundTask(Context context, NotificationManager nManager, int nId) { Resources r = context.getResources(); // Prepare all the output metadata mImageTime = System.currentTimeMillis(); mImageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(mImageTime)); mImageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath(); mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, mImageDate); mImageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, mImageDir, SCREENSHOTS_DIR_NAME, mImageFileName); // Show the intermediate notification mLaunchIntent = new Intent(Intent.ACTION_VIEW); mLaunchIntent.setDataAndType(Uri.fromFile(new File(mImageFilePath)), "image/png"); mLaunchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mNotificationId = nId; mNotificationBuilder = new Notification.Builder(context) .setTicker(r.getString(R.string.screenshot_saving_ticker)) .setContentTitle(r.getString(R.string.screenshot_saving_title)) .setContentText(r.getString(R.string.screenshot_saving_text)) .setSmallIcon(android.R.drawable.ic_menu_gallery) .setWhen(System.currentTimeMillis()); Notification n = mNotificationBuilder.getNotification(); n.flags |= Notification.FLAG_NO_CLEAR; mNotificationManager = nManager; mNotificationManager.notify(nId, n); } @Override protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) { if (params.length != 1) return null; Loading @@ -91,23 +126,15 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi Bitmap image = params[0].image; try { long currentTime = System.currentTimeMillis(); String date = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(currentTime)); String imageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES).getAbsolutePath(); String imageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, date); String imageFilePath = String.format(SCREENSHOT_FILE_PATH_TEMPLATE, imageDir, SCREENSHOTS_DIR_NAME, imageFileName); // Save the screenshot to the MediaStore ContentValues values = new ContentValues(); ContentResolver resolver = context.getContentResolver(); values.put(MediaStore.Images.ImageColumns.DATA, imageFilePath); values.put(MediaStore.Images.ImageColumns.TITLE, imageFileName); values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, imageFileName); values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_ADDED, currentTime); values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, currentTime); values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath); values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName); values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName); values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime); values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime); values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime); values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png"); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); Loading @@ -118,7 +145,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // update file size in the database values.clear(); values.put(MediaStore.Images.ImageColumns.SIZE, new File(imageFilePath).length()); values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length()); resolver.update(uri, values, null, null); params[0].result = 0; Loading @@ -135,12 +162,22 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi protected void onPostExecute(SaveImageInBackgroundData params) { if (params.result > 0) { // Show a message that we've failed to save the image to disk Toast.makeText(params.context, R.string.screenshot_failed_toast, Toast.LENGTH_SHORT).show(); GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager); } else { // Show a message that we've saved the screenshot to disk Toast.makeText(params.context, R.string.screenshot_saving_toast, Toast.LENGTH_SHORT).show(); // Show the final notification to indicate screenshot saved Resources r = params.context.getResources(); mNotificationBuilder .setTicker(r.getString(R.string.screenshot_saved_title)) .setContentTitle(r.getString(R.string.screenshot_saved_title)) .setContentText(r.getString(R.string.screenshot_saved_text)) .setContentIntent(PendingIntent.getActivity(params.context, 0, mLaunchIntent, 0)) .setWhen(System.currentTimeMillis()) .setAutoCancel(true); Notification n = mNotificationBuilder.getNotification(); n.flags &= ~Notification.FLAG_NO_CLEAR; mNotificationManager.notify(mNotificationId, n); } params.finisher.run(); }; Loading @@ -154,22 +191,21 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi */ class GlobalScreenshot { private static final String TAG = "GlobalScreenshot"; private static final int SCREENSHOT_FADE_IN_DURATION = 900; private static final int SCREENSHOT_NOTIFICATION_ID = 789; private static final int SCREENSHOT_FADE_IN_DURATION = 500; private static final int SCREENSHOT_FADE_OUT_DELAY = 1000; private static final int SCREENSHOT_FADE_OUT_DURATION = 450; private static final int TOAST_FADE_IN_DURATION = 500; private static final int TOAST_FADE_OUT_DELAY = 1000; private static final int TOAST_FADE_OUT_DURATION = 500; private static final int SCREENSHOT_FADE_OUT_DURATION = 300; private static final float BACKGROUND_ALPHA = 0.65f; private static final float SCREENSHOT_SCALE = 0.85f; private static final float SCREENSHOT_MIN_SCALE = 0.7f; private static final float SCREENSHOT_ROTATION = -6.75f; // -12.5f; private static final float SCREENSHOT_SCALE_FUDGE = 0.075f; // To account for the border padding private static final float SCREENSHOT_SCALE = 0.8f; private static final float SCREENSHOT_MIN_SCALE = 0.775f; private Context mContext; private LayoutInflater mLayoutInflater; private IWindowManager mIWindowManager; private WindowManager mWindowManager; private WindowManager.LayoutParams mWindowLayoutParams; private NotificationManager mNotificationManager; private Display mDisplay; private DisplayMetrics mDisplayMetrics; private Matrix mDisplayMatrix; Loading @@ -182,10 +218,15 @@ class GlobalScreenshot { private AnimatorSet mScreenshotAnimation; // General use cubic interpolator final TimeInterpolator mCubicInterpolator = new TimeInterpolator() { // Fade interpolators final TimeInterpolator mFadeInInterpolator = new TimeInterpolator() { public float getInterpolation(float t) { return t*t*t; return (float) Math.pow(t, 1.5f); } }; final TimeInterpolator mFadeOutInterpolator = new TimeInterpolator() { public float getInterpolation(float t) { return (float) t; } }; // The interpolator used to control the background alpha at the start of the animation Loading Loading @@ -237,6 +278,8 @@ class GlobalScreenshot { PixelFormat.TRANSLUCENT); mWindowLayoutParams.setTitle("ScreenshotAnimation"); mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); } Loading @@ -248,7 +291,8 @@ class GlobalScreenshot { data.context = mContext; data.image = mScreenBitmap; data.finisher = finisher; new SaveImageInBackgroundTask().execute(data); new SaveImageInBackgroundTask(mContext, mNotificationManager, SCREENSHOT_NOTIFICATION_ID) .execute(data); } /** Loading Loading @@ -300,8 +344,7 @@ class GlobalScreenshot { // If we couldn't take the screenshot, notify the user if (mScreenBitmap == null) { Toast.makeText(mContext, R.string.screenshot_failed_toast, Toast.LENGTH_SHORT).show(); notifyScreenshotError(mContext, mNotificationManager); finisher.run(); return; } Loading Loading @@ -341,12 +384,13 @@ class GlobalScreenshot { } private ValueAnimator createScreenshotFadeInAnimation() { ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); anim.setInterpolator(mCubicInterpolator); anim.setInterpolator(mFadeInInterpolator); anim.setDuration(SCREENSHOT_FADE_IN_DURATION); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { mBackgroundView.setVisibility(View.VISIBLE); mScreenshotContainerView.setTranslationY(0f); mScreenshotContainerView.setVisibility(View.VISIBLE); } }); Loading @@ -356,18 +400,19 @@ class GlobalScreenshot { float t = ((Float) animation.getAnimatedValue()).floatValue(); mBackgroundView.setAlpha(mBackgroundViewAlphaInterpolator.getInterpolation(t) * BACKGROUND_ALPHA); float scaleT = SCREENSHOT_SCALE + (1f - t) * SCREENSHOT_SCALE; float scaleT = SCREENSHOT_SCALE + (1f - t) * (1f - SCREENSHOT_SCALE) + SCREENSHOT_SCALE_FUDGE; mScreenshotContainerView.setAlpha(t*t*t*t); mScreenshotContainerView.setScaleX(scaleT); mScreenshotContainerView.setScaleY(scaleT); mScreenshotContainerView.setRotation(t * SCREENSHOT_ROTATION); } }); return anim; } private ValueAnimator createScreenshotFadeOutAnimation() { ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f); anim.setInterpolator(mCubicInterpolator); anim.setInterpolator(mFadeOutInterpolator); anim.setStartDelay(SCREENSHOT_FADE_OUT_DELAY); anim.setDuration(SCREENSHOT_FADE_OUT_DURATION); anim.addListener(new AnimatorListenerAdapter() { Loading @@ -381,8 +426,9 @@ class GlobalScreenshot { @Override public void onAnimationUpdate(ValueAnimator animation) { float t = ((Float) animation.getAnimatedValue()).floatValue(); float scaleT = SCREENSHOT_MIN_SCALE + t*(SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE); float scaleT = SCREENSHOT_MIN_SCALE + t * (SCREENSHOT_SCALE - SCREENSHOT_MIN_SCALE) + SCREENSHOT_SCALE_FUDGE; mScreenshotContainerView.setAlpha(t); mScreenshotContainerView.setScaleX(scaleT); mScreenshotContainerView.setScaleY(scaleT); Loading @@ -391,4 +437,19 @@ class GlobalScreenshot { }); return anim; } static void notifyScreenshotError(Context context, NotificationManager nManager) { Resources r = context.getResources(); // Clear all existing notification, compose the new notification and show it Notification n = new Notification.Builder(context) .setTicker(r.getString(R.string.screenshot_failed_title)) .setContentTitle(r.getString(R.string.screenshot_failed_title)) .setContentText(r.getString(R.string.screenshot_failed_text)) .setSmallIcon(android.R.drawable.ic_menu_report_image) .setWhen(System.currentTimeMillis()) .setAutoCancel(true) .getNotification(); nManager.notify(SCREENSHOT_NOTIFICATION_ID, n); } }
packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +0 −14 Original line number Diff line number Diff line Loading @@ -17,26 +17,12 @@ package com.android.systemui.screenshot; import android.app.Service; import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import com.android.internal.app.AlertActivity; import com.android.internal.app.AlertController; import com.android.systemui.R; public class TakeScreenshotService extends Service { private static final String TAG = "TakeScreenshotService"; Loading
packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java +22 −0 Original line number Diff line number Diff line Loading @@ -146,4 +146,26 @@ public abstract class StatusBar extends SystemUI implements CommandQueue.Callbac mDoNotDisturb = new DoNotDisturb(mContext); } protected View updateNotificationVetoButton(View row, StatusBarNotification n) { View vetoButton = row.findViewById(R.id.veto); if (n.isClearable()) { final String _pkg = n.pkg; final String _tag = n.tag; final int _id = n.id; vetoButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { mBarService.onNotificationClear(_pkg, _tag, _id); } catch (RemoteException ex) { // system process is dead if we're here. } } }); vetoButton.setVisibility(View.VISIBLE); } else { vetoButton.setVisibility(View.GONE); } return vetoButton; } }