/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.talkback.labeling;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.android.talkback.R;
import com.android.utils.LogUtils;
import com.android.utils.labeling.CustomLabelManager;
import com.android.utils.labeling.Label;
import com.android.utils.labeling.LabelProviderClient;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* An activity for managing custom labels in TalkBack for a specific package.
*/
public class LabelManagerPackageActivity extends Activity {
/** Labeling requires new accessibility APIs in JellyBean MR2 (API 18). */
public static final int MIN_API_LEVEL = Build.VERSION_CODES.JELLY_BEAN_MR2;
public static final String EXTRA_PACKAGE_NAME = "packageName";
private LabelProviderClient mLabelProviderClient;
private String mPackageName;
private ListView mLabelList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.label_manager_labels);
final Intent intent = getIntent();
if (!intent.hasExtra(EXTRA_PACKAGE_NAME)) {
throw new IllegalArgumentException("Intent missing package name extra.");
}
mPackageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
final PackageManager packageManager = getPackageManager();
CharSequence applicationLabel;
Drawable packageIcon;
try {
packageIcon = packageManager.getApplicationIcon(mPackageName);
final PackageInfo packageInfo = packageManager.getPackageInfo(mPackageName, 0);
applicationLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo);
} catch (NameNotFoundException e) {
LogUtils.log(this, Log.INFO, "Could not load package info for package %s.",
mPackageName);
packageIcon = packageManager.getDefaultActivityIcon();
applicationLabel = mPackageName;
}
setTitle(getString(R.string.label_manager_package_title, applicationLabel));
final ActionBar actionBar = getActionBar();
actionBar.setIcon(packageIcon);
actionBar.setDisplayHomeAsUpEnabled(true);
mLabelList = (ListView) findViewById(R.id.label_list);
mLabelProviderClient = new LabelProviderClient(this, LabelProvider.AUTHORITY);
}
@Override
protected void onResume() {
super.onResume();
new UpdateLabelsTask().execute();
}
@Override
protected void onDestroy() {
super.onDestroy();
mLabelProviderClient.shutdown();
}
/**
* Finishes the activity when the up button is pressed on the action bar.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* An adapter that processes information about labels for a given package.
*/
private class LabelAdapter extends ArrayAdapter<Label> {
private final LayoutInflater mLayoutInflater;
public LabelAdapter(Context context, int textViewResourceId, List<Label> items) {
super(context, textViewResourceId, items);
mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@SuppressWarnings("unchecked")
@Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = mLayoutInflater.inflate(R.layout.label_manager_label_row, parent, false);
}
final Label label = getItem(position);
if (label == null) {
return view;
}
final TextView textView = (TextView) view.findViewById(R.id.label_text);
textView.setText(label.getText());
final TextView timestampView = (TextView) view.findViewById(R.id.label_timestamp);
final DateFormat dateFormat = new SimpleDateFormat();
final Date date = new Date(label.getTimestamp());
final String timestampMessage
= getString(R.string.label_manager_timestamp_text, dateFormat.format(date));
timestampView.setText(timestampMessage);
final ImageView iconImage = (ImageView) view.findViewById(R.id.icon_image);
new LoadScreenshotTask(label, iconImage).execute();
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
final Context context = LabelManagerPackageActivity.this;
LabelDialogManager.editLabel(context, label, false /* overlay */);
// TODO: Also add intent for deleting the label.
}
});
return view;
}
}
/**
* A task for getting labels for the package displayed in the current
* activity and updating the adapter with those labels.
*/
private class UpdateLabelsTask extends AsyncTask<Void, Void, List<Label>> {
private String mLocale;
@Override
protected void onPreExecute() {
mLocale = CustomLabelManager.getDefaultLocale();
}
@Override
protected List<Label> doInBackground(Void... params) {
LogUtils.log(this, Log.VERBOSE, "Spawning new UpdateLabelsTask(%d) for (%s, %s).",
hashCode(), mPackageName, mLocale);
final Map<String, Label> labelsMap
= mLabelProviderClient.getLabelsForPackage(mPackageName, mLocale);
return new ArrayList<>(labelsMap.values());
}
@Override
protected void onPostExecute(List<Label> result) {
mLabelList.setAdapter(new LabelAdapter(LabelManagerPackageActivity.this,
R.layout.label_manager_label_row, result));
}
}
/**
* A task for loading a screenshot from a label into a view.
*/
private class LoadScreenshotTask extends AsyncTask<Void, Void, Drawable> {
private Label mLabel;
private ImageView mImageView;
/**
* Constructs a new task for loading a screenshot.
*
* @param label The label from which to load the screenshot.
* @param imageView The view into which to load the screenshot.
*/
public LoadScreenshotTask(Label label, ImageView imageView) {
mLabel = label;
mImageView = imageView;
}
@Override
protected Drawable doInBackground(Void... params) {
final String screenshotPath = mLabel.getScreenshotPath();
LogUtils.log(this, Log.VERBOSE, "Spawning new LoadScreenshotTask(%d) for %s.",
hashCode(), screenshotPath);
return Drawable.createFromPath(screenshotPath);
}
@Override
protected void onPostExecute(Drawable result) {
mImageView.setImageDrawable(result);
mImageView.invalidate();
}
}
}