Use activity instead of dialog

This commit is contained in:
fkloft 2013-07-26 19:13:25 +02:00
parent 2b7ac5605b
commit 50d1b643fc
11 changed files with 420 additions and 207 deletions

View File

@ -72,12 +72,38 @@
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<activity
android:name="com.cradle.iitc_mobile.IITC_Settings"
android:theme="@style/AppBaseTheme"
android:label="@string/app_name"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"/>
<activity
android:name=".share.ShareActivity"
android:label="@string/app_name"
android:noHistory="true"
android:parentActivityName="com.cradle.iitc_mobile.IITC_Mobile"
android:theme="@android:style/Theme.Holo.Light.DarkActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.cradle.iitc_mobile.IITC_Mobile"/>
</activity>
<activity
android:name=".share.SendToClipboard"
android:enabled="true"
android:excludeFromRecents="true"
android:exported="false"
android:label="Copy to clipboard"
android:noHistory="false">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
<!-- START Used for Samsung Multi-Window support -->
<uses-library
android:name="com.sec.android.app.multiwindow"
@ -86,7 +112,6 @@
<meta-data
android:name="com.sec.android.support.multiwindow"
android:value="true"/>
<meta-data
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W"
android:resource="@dimen/app_defaultsize_w"/>

Binary file not shown.

View File

@ -0,0 +1,6 @@
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ShareActivity"/>

View File

@ -8,4 +8,6 @@
<dimen name="app_minimumsize_w">400dip</dimen>
<dimen name="app_minimumsize_h">200dip</dimen>
<dimen name="icon_margin">8dp</dimen>
</resources>

View File

@ -5,7 +5,6 @@ import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -13,11 +12,13 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle;
import android.content.Intent;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
import com.cradle.iitc_mobile.share.ShareActivity;
// provide communication between IITC script and android app
public class IITC_JSInterface {
@ -38,15 +39,12 @@ public class IITC_JSInterface {
// open dialog to send geo intent for navigation apps like gmaps or waze etc...
@JavascriptInterface
public void intentPosLink(double lat, double lng, int zoom, String portalName) {
Bundle args = new Bundle();
args.putDouble("lat", lat);
args.putDouble("lng", lng);
args.putInt("zoom", zoom);
args.putString("title", portalName);
IITC_ShareDialog dialog = new IITC_ShareDialog();
dialog.setArguments(args);
dialog.show(((Activity) context).getFragmentManager(), "ShareDialog");
Intent intent = new Intent(context, ShareActivity.class);
intent.putExtra("lat", lat);
intent.putExtra("lng", lng);
intent.putExtra("zoom", zoom);
intent.putExtra("title", portalName);
context.startActivity(intent);
}
// disable javascript injection while spinner is enabled

View File

@ -1,194 +0,0 @@
package com.cradle.iitc_mobile;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class IITC_ShareDialog extends DialogFragment {
private abstract class Action {
private int mIcon;
private String mLabel;
private Action(String label, int icon) {
mLabel = label;
mIcon = icon;
}
abstract void invoke();
}
public class OnClickListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
mAdapter.getItem(which).invoke();
}
}
class ActionAdapter extends ArrayAdapter<Action> {
private LayoutInflater mInflater;
public ActionAdapter(Context context) {
super(context, android.R.layout.simple_list_item_1, ACTIONS);
mInflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Action action = getItem(position);
if (convertView == null)
convertView = mInflater.inflate(android.R.layout.simple_list_item_1, null);
TextView tv = (TextView) convertView;
tv.setText(action.mLabel);
tv.setCompoundDrawablePadding(8);
tv.setCompoundDrawablesWithIntrinsicBounds(action.mIcon, 0, 0, 0);
return convertView;
}
}
private final Action[] ACTIONS = {
new Action("Share…", R.drawable.ic_dialog_share) {
void invoke() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, getUrl());
intent.putExtra(Intent.EXTRA_SUBJECT, mTitle);
startIntent(intent);
}
},
new Action("View map with app…", R.drawable.location_map) {
void invoke() {
String geoUri = "geo:" + mLl;
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(geoUri));
startIntent(intent);
}
},
new Action("Open with browser…", R.drawable.ic_dialog_browser) {
void invoke() {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl()));
startIntent(intent);
}
},
new Action("Copy to clipboard", R.drawable.ic_dialog_copy) {
void invoke() {
ClipData clip = ClipData.newPlainText("Copied text", getUrl());
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(
Activity.CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(clip);
Toast.makeText(getActivity(), "copied to clipboard", Toast.LENGTH_SHORT).show();
}
}
};
private ActionAdapter mAdapter;
private boolean mIsPortal = true;
private String mLl;
private String mTitle;
private int mZoom;
private String getUrl() {
String url = "http://www.ingress.com/intel?ll=" + mLl + "&z=" + mZoom;
if (mIsPortal)
url += "&pll=" + mLl;
return url;
}
private void startIntent(Intent intent) {
// for geo: and Intel Map intents, the user may choose a default application to handle the intent. Since we have
// suitable intent filters declared, it might be that we *are* the default application. In theses cases, a list
// of designated applications is presented to the user
String packageName = getActivity().getPackageName();
PackageManager pm = getActivity().getPackageManager();
ResolveInfo mInfo = pm.resolveActivity(intent, 0);
if (mInfo.activityInfo.packageName.equals(packageName)) {
// note: Intent.createChooser would be shorter, but it also includes IITCm.
// Therefore, we'll filter the available activities
String label = null;
if (intent.getAction().equals(Intent.ACTION_SEND))
label = "Share via";
else if (intent.getAction().equals(Intent.ACTION_VIEW))
label = "Open with";
List<Intent> intents = new ArrayList<Intent>();
List<ResolveInfo> activities = getActivity().getPackageManager().queryIntentActivities(intent, 0);
if (!activities.isEmpty()) {
for (ResolveInfo resolveInfo : activities) {
ComponentInfo info;
if (resolveInfo.activityInfo != null)
info = resolveInfo.activityInfo;
else
// Exactly one if these two must be non-null (according to docs)
info = resolveInfo.serviceInfo;
if (info.packageName.equals(packageName)) // don't show IITCm
continue;
// setComponent is used to route the intent towards the component
// setPackage is used to prevent Android from showing IITCm
// (without a package set, Android would still show all available components, including IITCm)
intents.add(new Intent(intent)
.setComponent(new ComponentName(info.packageName, info.name))
.setPackage(info.packageName));
}
intent = Intent.createChooser(intents.remove(intents.size() - 1), label);
intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents.toArray(new Parcelable[] {}));
}
}
startActivity(intent);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle args = getArguments();
mTitle = args.getString("title");
mLl = args.getDouble("lat") + "," + args.getDouble("lng");
mZoom = args.getInt("zoom");
if (mTitle == null) {
mTitle = "Intel Map";
mIsPortal = false;
}
mAdapter = new ActionAdapter(getActivity());
return new AlertDialog.Builder(getActivity())
.setTitle(mTitle)
.setAdapter(mAdapter, new OnClickListener())
.create();
}
}

View File

@ -0,0 +1,55 @@
package com.cradle.iitc_mobile.share;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
public class IntentFragment extends Fragment implements OnScrollListener, OnItemClickListener {
private Intent mIntent;
private IntentListView mListView;
private int mScrollIndex, mScrollTop;
public String getTitle() {
return getArguments().getString("title");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle args = getArguments();
mIntent = args.getParcelable("intent");
mListView = new IntentListView(getActivity());
mListView.setIntent(mIntent);
if (mScrollIndex != -1 && mScrollTop != -1)
mListView.setSelectionFromTop(mScrollIndex, mScrollTop);
mListView.setOnScrollListener(this);
mListView.setOnItemClickListener(this);
return mListView;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = mListView.getTargetIntent(position);
startActivity(intent);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mScrollIndex = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt(0);
mScrollTop = (v == null) ? 0 : v.getTop();
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}

View File

@ -0,0 +1,37 @@
package com.cradle.iitc_mobile.share;
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
public class IntentFragmentAdapter extends FragmentPagerAdapter {
private List<IntentFragment> mTabs;
public IntentFragmentAdapter(FragmentManager fm) {
super(fm);
mTabs = new ArrayList<IntentFragment>();
}
public void add(IntentFragment fragment) {
mTabs.add(fragment);
}
@Override
public int getCount() {
return mTabs.size();
}
@Override
public Fragment getItem(int position) {
return mTabs.get(position);
}
@Override
public CharSequence getPageTitle(int position) {
return mTabs.get(position).getTitle();
}
}

View File

@ -0,0 +1,136 @@
package com.cradle.iitc_mobile.share;
import java.util.List;
import com.cradle.iitc_mobile.R;
import android.app.Activity;
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.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class IntentListView extends ListView {
private class IntentAdapter extends ArrayAdapter<ResolveInfo>
{
private IntentAdapter()
{
super(IntentListView.this.getContext(), android.R.layout.simple_list_item_1);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater();
TextView view = (TextView) inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
ActivityInfo info = getItem(position).activityInfo;
CharSequence label = info.loadLabel(mPackageManager);
Drawable icon = info.loadIcon(mPackageManager);
view.setText(label);
view.setCompoundDrawablePadding((int) getResources().getDimension(R.dimen.icon_margin));
view.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
return view;
}
}
private IntentAdapter mAdapter;
private PackageManager mPackageManager;
private Intent mIntent = null;
public IntentListView(Context context) {
super(context);
init();
}
public IntentListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public IntentListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mPackageManager = getContext().getPackageManager();
mAdapter = new IntentAdapter();
setAdapter(mAdapter);
}
public ResolveInfo getItem(int position) {
return mAdapter.getItem(position);
}
public void setIntent(Intent intent)
{
mIntent = intent;
mAdapter.setNotifyOnChange(false);
mAdapter.clear();
String packageName = getContext().getPackageName();
// TODO find default, show on top
// TODO exclude IITCm
List<ResolveInfo> activities = mPackageManager.queryIntentActivities(intent, 0);
ResolveInfo defaultTarget = mPackageManager.resolveActivity(intent, 0);
boolean hasCopyIntent = false;
for (ResolveInfo resolveInfo : activities) { // search for "Copy to clipboard" target, provided by Drive
if (resolveInfo.activityInfo.name.equals("com.google.android.apps.docs.app.SendTextToClipboardActivity")
&& resolveInfo.activityInfo.packageName.equals("com.google.android.apps.docs"))
hasCopyIntent = true;
}
for (int i = 0; i < activities.size(); i++) { // use traditional loop since List may change during interation
ResolveInfo info = activities.get(i);
ActivityInfo activity = info.activityInfo;
// remove all IITCm intents, except for SendToClipboard in case Drive is not installed
if (activity.packageName.equals(packageName))
{
if (hasCopyIntent || !activity.name.equals(SendToClipboard.class.getCanonicalName()))
{
activities.remove(i);
i--;
continue;
}
}
// move default Intent to top
if (info.activityInfo.packageName.equals(defaultTarget.activityInfo.packageName)
&& info.activityInfo.name.equals(defaultTarget.activityInfo.name))
{
activities.remove(i);
activities.add(0, info);
}
}
mAdapter.addAll(activities);
mAdapter.setNotifyOnChange(true);
mAdapter.notifyDataSetChanged();
}
public Intent getTargetIntent(int position) {
ActivityInfo activity = mAdapter.getItem(position).activityInfo;
Intent intent = new Intent(mIntent)
.setComponent(new ComponentName(activity.packageName, activity.name))
.setPackage(activity.packageName);
return intent;
}
}

View File

@ -0,0 +1,28 @@
package com.cradle.iitc_mobile.share;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
public class SendToClipboard extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("Copied Text ", text);
clipboard.setPrimaryClip(clip);
Toast.makeText(this, "Copied to clipboard…", Toast.LENGTH_SHORT).show();
finish();
setResult(RESULT_OK);
}
}

View File

@ -0,0 +1,120 @@
package com.cradle.iitc_mobile.share;
import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.support.v4.view.ViewPager;
import android.view.MenuItem;
import com.cradle.iitc_mobile.R;
public class ShareActivity extends FragmentActivity implements ActionBar.TabListener {
private boolean mIsPortal;
private String mLl;
private String mTitle;
private int mZoom;
IntentFragmentAdapter mFragmentAdapter;
ViewPager mViewPager;
private void addTab(Intent intent, String label)
{
IntentFragment fragment = new IntentFragment();
Bundle args = new Bundle();
args.putParcelable("intent", intent);
args.putString("title", label);
fragment.setArguments(args);
mFragmentAdapter.add(fragment);
}
private String getUrl() {
String url = "http://www.ingress.com/intel?ll=" + mLl + "&z=" + mZoom;
if (mIsPortal)
url += "&pll=" + mLl;
return url;
}
private void setupIntents() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, getUrl());
intent.putExtra(Intent.EXTRA_SUBJECT, mTitle);
addTab(intent, "Share");
String geoUri = "geo:" + mLl;
intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(geoUri));
addTab(intent, "Map");
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getUrl()));
addTab(intent, "Browser");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_share);
Intent intent = getIntent();
mTitle = intent.getStringExtra("title");
mLl = intent.getDoubleExtra("lat", 0) + "," + intent.getDoubleExtra("lng", 0);
mZoom = intent.getIntExtra("zoom", 0);
if (mTitle == null) {
mTitle = "Intel Map";
mIsPortal = false;
}
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayHomeAsUpEnabled(true);
mFragmentAdapter = new IntentFragmentAdapter(getSupportFragmentManager());
setupIntents();
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mFragmentAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mFragmentAdapter.getCount(); i++) {
IntentFragment fragment = (IntentFragment) mFragmentAdapter.getItem(i);
actionBar.addTab(actionBar
.newTab()
.setText(fragment.getTitle())
.setTabListener(this));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
}