This question already has answers here:
Extending from two classes
(13 answers)
Closed 7 years ago.
I'm developing an AR Android App using Metaio. I need to show some data when a real object has been tracked. To do this I register a callback, this is the best way that I have found.
Unfortunately to use correctly getFragmentManager(), I need to import Activity properties but i can't extend the class (already extended).
I think that getContext is the right way, but I do not know how to implement it.
This is the callback register in main activity:
metaioSDK.registerCallback(new ProvaTracking());
This is the Tracking class:
package com.metaio.Example;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.Log;
import com.metaio.sdk.jni.IMetaioSDKCallback;
import com.metaio.sdk.jni.TrackingValues;
import com.metaio.sdk.jni.TrackingValuesVector;
public class ProvaTracking extends IMetaioSDKCallback {
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onTrackingEvent(TrackingValuesVector trackingValuesVector) {
super.onTrackingEvent(trackingValuesVector);
for (int i=0; i<trackingValuesVector.size(); i++)
{
final TrackingValues v = trackingValuesVector.get(i);
if (v.isTrackingState())
{
TestFragment trendsFragment = new TestFragment();
getFragmentManager().beginTransaction().add(android.R.id.content, trendsFragment).commit();
Log.d("Alessandro", "Works!!");
}
}
}
}
Add a constructor that takes in Context (Note that you want the Activity context, not the application context)
so you would change your class to be:
public class ProvaTracking extends IMetaioSDKCallback {
private Contect mCtx;
public ProvaTracking(Context context) {
mCtx = context;
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onTrackingEvent(TrackingValuesVector trackingValuesVector) {
super.onTrackingEvent(trackingValuesVector);
for (int i=0; i<trackingValuesVector.size(); i++)
{
final TrackingValues v = trackingValuesVector.get(i);
if (v.isTrackingState())
{
TestFragment trendsFragment = new TestFragment();
if (mCtx instanceof Activity)
((Activity) mCtx).getFragmentManager().beginTransaction().add(android.R.id.content, trendsFragment).commit();
Log.d("Alessandro", "Works!!");
}
}
}
}
then call it with metaioSDK.registerCallback(new ProvaTracking(getContext()));
Related
Hi I am trying to use the https://github.com/Swati4star/Images-to-PDF ImagesToPDF function from this library. I have added all the classes required in my application.
Now I have used picasso in my application before adding the ImagesToPDF function.
Now after adding it I am getting following error :
java.lang.NoSuchMethodError: No static method with(Landroid/content/Context;)Lcom/squareup/picasso/Picasso; in class Lcom/squareup/picasso/Picasso; or its super classes (declaration of 'com.squareup.picasso.Picasso' appears in /data/app/com.example.onboardingversion2-sJCkixxNOR2KPNLmYYdvpQ==/base.apk!classes2.dex)
Getting error in following function :
/**
* Opens Matisse activity to select Images
*/
private void selectImages() {
Matisse.from(this)
.choose(MimeType.ofImage(), false)
.countable(true)
.capture(true)
.captureStrategy(new CaptureStrategy(true, AUTHORITY_APP))
.maxSelectable(1000)
.imageEngine(new PicassoEngine())
.forResult(INTENT_REQUEST_GET_IMAGES);
}
app gets crashed and gives error. I added application and set Multidex
public class MyApplication extends Application {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(base);
}
}
I also added multidexEnabled true in gradle. Still its throwing the error.
Please help. Thank you.
Picasso in not updated for about 4 years, it has many issues. Maybe You should switch to Glide
The problem is in the line
.imageEngine(new PicassoEngine())
where PicassoEngine() class uses Picasso.with(context).... module which is deprecated. The solution is you have to create a new class, name it NewPicassoEngine() as below;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import com.zhihu.matisse.engine.ImageEngine;
public class NewPicassoEngine implements ImageEngine {
#Override
public void loadThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView, Uri uri) {
Picasso.get().load(uri).placeholder(placeholder)
.resize(resize, resize)
.centerCrop()
.into(imageView);
}
#Override
public void loadGifThumbnail(Context context, int resize, Drawable placeholder, ImageView imageView,
Uri uri) {
loadThumbnail(context, resize, placeholder, imageView, uri);
}
#Override
public void loadImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {
Picasso.get().load(uri).resize(resizeX, resizeY).priority(Picasso.Priority.HIGH)
.centerInside().into(imageView);
}
#Override
public void loadGifImage(Context context, int resizeX, int resizeY, ImageView imageView, Uri uri) {
loadImage(context, resizeX, resizeY, imageView, uri);
}
#Override
public boolean supportAnimatedGif() {
return false;
}}
and use it as;
private void selectImages() {
Matisse.from(this)
.choose(MimeType.ofImage(), false)
.countable(true)
.capture(true)
.captureStrategy(new CaptureStrategy(true, AUTHORITY_APP))
.maxSelectable(1000)
.imageEngine(new NewPicassoEngine())
.forResult(INTENT_REQUEST_GET_IMAGES);
}
This will solve your problem.
GlideEngine() work for me using latest dependency
fun selectImages(frag: Fragment?, requestCode: Int) {
Matisse.from(frag)
.choose(MimeType.ofImage(), false)
.countable(true)
.capture(true)
.captureStrategy(CaptureStrategy(true, AUTHORITY_APP))
.maxSelectable(1000)
.imageEngine(GlideEngine())
.forResult(requestCode)
}
I have search now for hours through the internet and have found nothing substantial so far. The thing that I want to do is a multi choice preference view, that disables the last item and reenables it, if it is not alone anymore.
I through so far about taking the super class force read the private variables in there to write my own onPrepareDialogBuilder(AlertDialog.Builder builder). Which is configuring its own OnMultiChoiceClickListener that jumps in, in the moment where has only one item left. The problem here is, that I use a bad practice force read of a private variable and that I have so far no idea how to get the checkbox item and how to disable it. But I think looking even deeper into the Android SDK will solve this problem.
At the end, if nothing works, solving the problem with doing an overwrite the OnPreferenceChangeListener to display a toast if the user has less than one item selected. But user friendliness is a high value, that needs to be earned and that often isn't easy.
Thx.
import android.content.Context;
import android.preference.MultiSelectListPreference;
import android.util.AttributeSet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends MultiSelectListPreference {
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
List<CharSequence> humanU = new ArrayList<>();
List<CharSequence> machineU = new ArrayList<>();
Units[] all = Units.values(); // Units is a enum with a rewriten to string statement.
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
setEntries(humanU.toArray(new CharSequence[humanU.size()]));
setEntryValues(machineU.toArray(new CharSequence[machineU.size()]));
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
}
}
Okay. To answer my own question here after the motto "self is the man": I ended up with programming my own preference panel. Below is the code. If somebody likes to look over it and give some times how to make it even more stable: feel free.
But to sum up what I did: I created my own ArrayAdapter. But DialogPreference didn't allowed me to create my own multi selector. You need to change the final dialog fragment to create a working multi selector list (see here: https://stackoverflow.com/a/17907379/5759814). That is not an easy task if you work with the DialogPreferences. The reason is these few amounts of code:
/**
* Shows the dialog associated with this Preference. This is normally initiated
* automatically on clicking on the preference. Call this method if you need to
* show the dialog on some other event.
*
* #param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
.setPositiveButton(mPositiveButtonText, this)
.setNegativeButton(mNegativeButtonText, this);
View contentView = onCreateDialogView();
if (contentView != null) {
onBindDialogView(contentView);
mBuilder.setView(contentView);
} else {
mBuilder.setMessage(mDialogMessage);
}
onPrepareDialogBuilder(mBuilder);
getPreferenceManager().registerOnActivityDestroyListener(this);
// Create the dialog
final Dialog dialog = mDialog = mBuilder.create();
if (state != null) {
dialog.onRestoreInstanceState(state);
}
if (needInputMethod()) {
requestInputMethod(dialog);
}
dialog.setOnDismissListener(this);
dialog.show();
}
As you can see here is a method triggered to change my dialog builder with onPrepareDialogBuilder, but it doesn't seem like that there is any other function triggered afterwards, that would allow me to change the dialog directly after its creation. And the second idea of changing the onPrepareDialogBuilder so that I can init everything there, doesn't really help, because I end up with displayed dialog windows. That lead me to my decision of creating my completely own Preference class. With that decision I loose all those nice prepared functions like onRestoreInstanceState and Co, but I now have an application with a much more persistent flow, that doesn't do any stupid things when I select zero units for my thermal view.
Below the non commented code. I'm sorry, but I think its simple enough for everybody who landing here.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import georg.com.flironetest_01.Variables.Units;
/**
* Created by Georg on 16/03/16.
*/
public class UnitMultipleSelectorPreference extends Preference implements DialogInterface.OnClickListener, Preference.OnPreferenceClickListener {
String[] human_entries = null;
String[] machine_entries = null;
public SharedPreferences prev;
public UnitMultipleSelectorPreference(Context context, AttributeSet attrs) {
super(context, attrs);
prev = getSharedPreferences();
List<String> humanU = new ArrayList<>();
List<String> machineU = new ArrayList<>();
Units[] all = Units.values();
for (Units elem : all) {
humanU.add(elem.toString());
machineU.add(elem.name());
}
human_entries = humanU.toArray(new String[humanU.size()]);
machine_entries = machineU.toArray(new String[machineU.size()]);
Set<String> mU = new HashSet<>();
mU.add(Units.C.name());
mU.add(Units.K.name());
setDefaultValue(mU);
setOnPreferenceClickListener(this);
}
boolean[] selected = new boolean[0];
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
if (prev == null)
return;
if (human_entries == null || machine_entries == null || human_entries.length != machine_entries.length ) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array which are both the same length");
}
selected = new boolean[human_entries.length];
for (int i = 0; i < human_entries.length; i++)
selected[i] = prefSet.contains(machine_entries[i]);
String[] stringObj = new String[human_entries.length];
int i = 0;
for(CharSequence ch : human_entries)
stringObj[i++] = ch.toString();
builder.setAdapter(new MyAdapter(getContext(), android.R.layout.simple_list_item_multiple_choice, stringObj), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog mDialog = builder.create();
mDialog.getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
mDialog.getListView().setItemsCanFocus(false);
mDialog.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Manage selected items here
ListView mParent = (ListView)parent;
if (mParent.getCheckedItemCount() >= 1)
selected[position] = mParent.isItemChecked(position);
if (mParent.getCheckedItemCount() == 0)
mParent.setItemChecked(position, true);
}
});
mDialog.show();
i = 0;
for (boolean select : selected)
mDialog.getListView().setItemChecked(i++, select);
}
#Override
public boolean onPreferenceClick(Preference preference) {
AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext());
mBuilder.setTitle(getTitle())
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this);
onPrepareDialogBuilder(mBuilder);
return true;
}
#Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "W:"+which + " | " + Arrays.toString(selected), Toast.LENGTH_SHORT).show();
switch (which) {
case -1:
if (isPersistent()) {
prefSet = new HashSet<>();
for (int i = 0; i < selected.length; i++) {
if (selected[i])
prefSet.add(machine_entries[i]);
}
getEditor().putStringSet(getKey(), prefSet).apply();
Toast.makeText(getContext(), "W:"+which + " | " + getSharedPreferences().getStringSet(getKey(),null).toString(), Toast.LENGTH_SHORT).show();
}
return;
}
}
public class MyAdapter extends ArrayAdapter<String> {
public MyAdapter(Context context, int textViewResourceId, String[] objects) {
super(context, textViewResourceId, objects);
}
#Override
public boolean isEnabled(int n) {
return true;
}
}
Set<String> prefSet;
#Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
prev = getSharedPreferences();
if(restorePersistedValue) {
prefSet = prev.getStringSet(getKey(), new HashSet<String>());
} else {
try {
prefSet = (Set<String>)defaultValue;
if(isPersistent())
getEditor().putStringSet(getKey(), prefSet);
} catch (ClassCastException e) {
Log.e("ERROR_CAST", "Error casting the default value to Set<String>.");
}
}
}
}
A really simple solution is to set a setOnPreferenceChangeListener and just return false if the new value would be empty.
All of the code is put into onCreatePreferences.
MultiSelectListPreference infoPreference = findPreference("information");
infoPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (size(newValue) == 0){
return false;
}
return true;
}
});
How can I add multiple showcaseviews to my layout...
I've tried this:
import com.github.amlcurran.showcaseview.sample.R;
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class MultipleShowcaseSampleActivity extends Activity {
private static final float SHOWCASE_KITTEN_SCALE = 1.2f;
private static final float SHOWCASE_LIKE_SCALE = 0.5f;
//ShowcaseViews mViews;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample_legacy);
findViewById(R.id.buttonLike).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(), R.string.like_message, Toast.LENGTH_SHORT).show();
}
});
//mOptions.block = false;
// mViews = new ShowcaseViews(this,
// new ShowcaseViews.OnShowcaseAcknowledged() {
// #Override
// public void onShowCaseAcknowledged(ShowcaseView showcaseView) {
// Toast.makeText(MultipleShowcaseSampleActivity.this, R.string.dismissed_message, Toast.LENGTH_SHORT).show();
// }
// });
// mViews.addView( new ShowcaseViews.ItemViewProperties(R.id.image,
// R.string.showcase_image_title,
// R.string.showcase_image_message,
// SHOWCASE_KITTEN_SCALE));
// mViews.addView( new ShowcaseViews.ItemViewProperties(R.id.buttonLike,
// R.string.showcase_like_title,
// R.string.showcase_like_message,
// SHOWCASE_LIKE_SCALE));
// mViews.show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
enableUp();
}
}
You can see the comment part, When I uncomment Showcaseview cant found those methods so maybe ShowcaseViews missing, anyway I tried to copy and create that class, but still need methods from showcaseview that cant be found.
Help Me.
Update: Ok according the answer below, I have a problem:
mViews = new ShowcaseView(this,
new ShowcaseView.setOnShowcaseEventListener() {
#Override
public void onShowCaseAcknowledged(ShowcaseView showcaseView) {
Toast.makeText(MultipleShowcaseSampleActivity.this, R.string.dismissed_message, Toast.LENGTH_SHORT).show();
}
});
mViews.addView( new ShowcaseView.ItemViewProperties(R.id.image,
R.string.showcase_image_title,
R.string.showcase_image_message,
SHOWCASE_KITTEN_SCALE));
mViews.addView( new ShowcaseView.ItemViewProperties(R.id.buttonLike,
R.string.showcase_like_title,
R.string.showcase_like_message,
SHOWCASE_LIKE_SCALE));
mViews.show();
On new ShowcaseView.setOnShowcaseEventListener() Cannot be resolve to a type
then new ShowcaseView.ItemViewProperties Cannot be resolve to a type too.
The library doesn't have any class called ShowCaseViews. It only has a class ShowCaseView.
If you are following this github example you have to have the class given in the link
EDIT Okay let me try and explain classes
There are 2 classes
ShowcaseView (in the library)
ShowcaseViews (in the example on Github)
You cannot say ShowcaseView.ItemProperties because ShowcaseView doesn't have them. They belong to ShowcaseViews. Hence they cannot be resolved or found.
OnShowcaseEventListener is a whole different class, contained in neither one of these but just exists separately and hence also when you say ShowcaseView.OnShowcaseEventListener it can't be resolved.
Change ShowcaseView.OnShowcaseEventListener to just OnShowcaseEventListener and ShowcaseView.ItemPropertiesto ShowcaseViews.ItemProperties
I used this code for adding a clock to my app:
<DigitalClock
android:id="#+id/digitalclock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize = "30sp"
/>
The problem is that it shows also seconds..there is a simple and fast way for hide those? I need just hours and minutes in hh:mm format instead of hh:mm:ss! any suggestions? Thanks!
Found the answer here, for anyone else looking for a working answer, here it is:
Clone/copy DigitalClock.java from android source
Change format strings within new CustomDigitalClock
package com.example;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.Calendar;
/**
* You have to make a clone of the file DigitalClock.java to use in your application, modify in the following manner:-
* private final static String m12 = "h:mm aa";
* private final static String m24 = "k:mm";
*/
public class CustomDigitalClock extends TextView {
Calendar mCalendar;
private final static String m12 = "h:mm aa";
private final static String m24 = "k:mm";
private FormatChangeObserver mFormatChangeObserver;
private Runnable mTicker;
private Handler mHandler;
private boolean mTickerStopped = false;
String mFormat;
public CustomDigitalClock(Context context) {
super(context);
initClock(context);
}
public CustomDigitalClock(Context context, AttributeSet attrs) {
super(context, attrs);
initClock(context);
}
private void initClock(Context context) {
Resources r = context.getResources();
if (mCalendar == null) {
mCalendar = Calendar.getInstance();
}
mFormatChangeObserver = new FormatChangeObserver();
getContext().getContentResolver().registerContentObserver(
Settings.System.CONTENT_URI, true, mFormatChangeObserver);
setFormat();
}
#Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler();
/**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(mFormat, mCalendar));
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mTickerStopped = true;
}
/**
* Pulls 12/24 mode from system settings
*/
private boolean get24HourMode() {
return android.text.format.DateFormat.is24HourFormat(getContext());
}
private void setFormat() {
if (get24HourMode()) {
mFormat = m24;
} else {
mFormat = m12;
}
}
private class FormatChangeObserver extends ContentObserver {
public FormatChangeObserver() {
super(new Handler());
}
#Override
public void onChange(boolean selfChange) {
setFormat();
}
}
}
Reference custom class within in layout xml
<com.example.CustomDigitalClock
android:id="#+id/fragment_clock_digital"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DigitalClock" />
Load CustomDigitalClock within activity/fragment
CustomDigitalClock dc = (CustomDigitalClock)
mFragmentView.findViewById(R.id.fragment_clock_digital);
The DigitalClock Javadoc states:
Class Overview
Like AnalogClock, but digital. Shows seconds. FIXME: implement
separate views for hours/minutes/seconds, so proportional fonts don't
shake rendering
Judging by the FIXME, the ability to hide portions of DigitalClock might be implemented eventually. I didn't find anything currently in the Javadoc or source code that would do what you want it to.
Unless you want to write your own class that extends DigitalClock (or your own clock implementation altogether), you could just cover the seconds portion of the DigitalClock with another element if it would serve your purpose.
I have a class Scores.java I need to know whats the correct way to create these. I get "The constructor Scores is not defined. Do I have to extend off everything in Android??
package com.threeuglymen.android.stuff;
import android.app.Application;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.util.Log;
public class Scores {
private Context mycontext;
public Scores (Context context) {
// TODO Auto-generated method stub
this.mycontext = context;
}
public void resetScores(){
try {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mycontext);
Editor edit = pref.edit();
edit.putInt("correct", 0);
edit.putInt("incorrect", 0);
edit.commit();
} catch (Exception e) {
Log.d("Scores", "Exception:" + e.toString());
}
return;
}
}
Thx for any guidance
Eric
What you have currently should work. In your main activity, don't call
Scores score = new Scores();
instead call
Scores score = new Scores(getContext());
Let me know if this works.
You probably want:
public class ScoresSub extends Scores
{
public ScoresSub(Context context)
{
super(context);
}
}
Since you defined a constructor taking parameters in Scores, the compiler doesn't provide a no-arg one.
When you create a class you don't always new to extend from another, all clases extend from the class Object and if you extend another like in this case class Application it is because you want its function and you want to make a variation of it or override some method and i think in this case you don't even need to extend from Application, because your class is not intended to be an Application so:
public class Scores {
private Context mycontext;
public Scores () {
this.mycontext = null;
}
public Scores (Context context) {
// TODO Auto-generated method stub
this.mycontext = context;
}
public void resetScores(){
try {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mycontext);
Editor edit = pref.edit();
edit.putInt("correct", 0);
edit.putInt("incorrect", 0);
edit.commit();
} catch (Exception e) {
Log.d("Scores", "Exception:" + e.toString());
}
return;
}
}
and i don't think you should have a problem.