/*
* Copyright (C) 2008 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 fm.last.android.activity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Config;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import fm.last.android.LastFMApplication;
import fm.last.android.R;
/**
* This activity is displayed when the system attempts to start an Intent for
* which there is more than one matching activity, allowing the user to decide
* which to go to. It is not normally used directly by application developers.
*/
public class ShareResolverActivity extends ListActivity {
private ResolveListAdapter mAdapter;
private PackageManager mPm;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent i = getIntent();
i.setType("text/plain");
i.setAction(Intent.ACTION_SEND);
String artist = i.getStringExtra(Share.INTENT_EXTRA_ARTIST);
String track = i.getStringExtra(Share.INTENT_EXTRA_TRACK);
String URL = "http://www.last.fm/music/" + Uri.encode(artist).replace("/", "%2f");
if(track != null)
URL += "/_/" + Uri.encode(track);
i.putExtra(Intent.EXTRA_TEXT, URL);
onCreate(icicle, i, getString(R.string.share_selectapplication));
}
protected void onCreate(Bundle savedInstanceState, Intent intent, CharSequence title) {
super.onCreate(savedInstanceState);
mPm = getPackageManager();
intent.setComponent(null);
setTitle(title);
mAdapter = new ResolveListAdapter(this, intent);
if (mAdapter.getCount() > 1) {
this.setListAdapter(mAdapter);
} else if (mAdapter.getCount() == 1) {
startActivity(mAdapter.intentForPosition(0));
finish();
return;
} else {
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = mAdapter.intentForPosition(position);
if (intent != null) {
try {
LastFMApplication.getInstance().tracker.trackEvent("Clicks", // Category
"share", // Action
intent.getComponent().getPackageName(), // Label
0); // Value
} catch (Exception e) {
//Google Analytics doesn't appear to be thread safe
}
startActivity(intent);
}
finish();
}
private final class DisplayResolveInfo {
ResolveInfo ri;
CharSequence displayLabel;
CharSequence extendedInfo;
DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel, CharSequence pInfo) {
ri = pri;
displayLabel = pLabel;
extendedInfo = pInfo;
}
}
private final class ResolveListAdapter extends BaseAdapter {
private final Intent mIntent;
private final LayoutInflater mInflater;
private List<DisplayResolveInfo> mList;
public ResolveListAdapter(Context context, Intent intent) {
mIntent = new Intent(intent);
mIntent.setComponent(null);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
List<ResolveInfo> rList = mPm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
int N;
if ((rList != null) && ((N = rList.size()) > 0)) {
// Only display the first matches that are either of equal
// priority or have asked to be default options.
ResolveInfo r0 = rList.get(0);
for (int i = 1; i < N; i++) {
ResolveInfo ri = rList.get(i);
if (Config.LOGV)
Log.v("ResolveListActivity", r0.activityInfo.name + "=" + r0.priority + "/" + r0.isDefault + " vs " + ri.activityInfo.name + "="
+ ri.priority + "/" + ri.isDefault);
if (r0.priority != ri.priority || r0.isDefault != ri.isDefault) {
while (i < N) {
rList.remove(i);
N--;
}
}
}
if (N > 1) {
ResolveInfo.DisplayNameComparator rComparator = new ResolveInfo.DisplayNameComparator(mPm);
Collections.sort(rList, rComparator);
}
// Check for applications with same name and use application
// name or
// package name if necessary
mList = new ArrayList<DisplayResolveInfo>();
List<ResolveInfo> lfmInfoQuery = mPm.queryIntentActivities(new Intent(ShareResolverActivity.this, Share.class),
PackageManager.MATCH_DEFAULT_ONLY);
ResolveInfo lfmInfo = lfmInfoQuery.get(0);
mList.add(new DisplayResolveInfo(lfmInfo, getString(R.string.app_name), getString(R.string.share_friendslist)));
r0 = rList.get(0);
int start = 0;
CharSequence r0Label = r0.loadLabel(mPm);
for (int i = 1; i < N; i++) {
if (r0Label == null) {
r0Label = r0.activityInfo.packageName;
}
ResolveInfo ri = rList.get(i);
CharSequence riLabel = ri.loadLabel(mPm);
if (riLabel == null) {
riLabel = ri.activityInfo.packageName;
}
if (riLabel.equals(r0Label)) {
continue;
}
processGroup(rList, start, (i - 1), r0, r0Label);
r0 = ri;
r0Label = riLabel;
start = i;
}
// Process last group
processGroup(rList, start, (N - 1), r0, r0Label);
}
}
private void processGroup(List<ResolveInfo> rList, int start, int end, ResolveInfo ro, CharSequence roLabel) {
// Process labels from start to i
int num = end - start + 1;
if (num == 1) {
// No duplicate labels. Use label for entry at start
mList.add(new DisplayResolveInfo(ro, roLabel, null));
} else {
boolean usePkg = false;
CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
if (startApp == null) {
usePkg = true;
}
if (!usePkg) {
// Use HashSet to track duplicates
HashSet<CharSequence> duplicates = new HashSet<CharSequence>();
duplicates.add(startApp);
for (int j = start + 1; j <= end; j++) {
ResolveInfo jRi = rList.get(j);
CharSequence jApp = jRi.activityInfo.applicationInfo.loadLabel(mPm);
if ((jApp == null) || (duplicates.contains(jApp))) {
usePkg = true;
break;
} else {
duplicates.add(jApp);
}
}
// Clear HashSet for later use
duplicates.clear();
}
for (int k = start; k <= end; k++) {
ResolveInfo add = rList.get(k);
if (usePkg) {
// Use application name for all entries from start to
// end-1
mList.add(new DisplayResolveInfo(add, roLabel, add.activityInfo.packageName));
} else {
// Use package name for all entries from start to end-1
mList.add(new DisplayResolveInfo(add, roLabel, add.activityInfo.applicationInfo.loadLabel(mPm)));
}
}
}
}
public Intent intentForPosition(int position) {
if (mList == null) {
return null;
}
Intent intent = new Intent(mIntent);
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
ActivityInfo ai = mList.get(position).ri.activityInfo;
intent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name));
return intent;
}
public int getCount() {
return mList != null ? mList.size() : 0;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = mInflater.inflate(R.layout.list_row, parent, false);
} else {
view = convertView;
}
bindView(view, mList.get(position));
return view;
}
private final void bindView(View view, DisplayResolveInfo info) {
TextView text = (TextView) view.findViewById(R.id.row_label);
TextView text2 = (TextView) view.findViewById(R.id.row_label_second);
ImageView icon = (ImageView) view.findViewById(R.id.row_icon);
text.setText(info.displayLabel);
if (info.extendedInfo != null) {
text2.setVisibility(View.VISIBLE);
text2.setText(info.extendedInfo);
} else {
text2.setVisibility(View.GONE);
}
icon.setImageDrawable(info.ri.loadIcon(mPm));
icon.setVisibility(View.VISIBLE);
}
}
}