Starting Camera Activity Cordova Plugin - java

Basically, what I want to do is to create Aztec code reader plugin.
So I need to open some kind of camera screen inside my app. I should do that inside my Java code, which right now looks like so:
public class AztecReaderPlugin extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
try {
if(action.equals("open")) {
Context context = cordova.getActivity().getApplicationContext();
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
callbackContext.success();
return true;
}
callbackContext.error("Something gone wrong!");
return false;
} catch (Exception e) {
callbackContext.error(e.getMessage());
return false;
}
}
}
It basically should execute the code inside MainActivity class. And the MainActivity class method onCreate looks like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
Button btnDoFocus = (Button)findViewById(R.id.buttonAutoFocus);
btnDoFocus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
preview.autoFocus();
}
});
Button btnDoAztec = (Button)findViewById(R.id.buttonDoAztec);
btnDoAztec.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
preview.setEnableReadAztecCode(true);
}
});
}
The thing is, when I did forget about AztecReaderPlugin, and run the MainActivity code as an standalone Android app, it works just like I would want.
I can't find any tutorial/post that would help me with my problem, and I don't have time to learn Android developing.
So my question is: How can I include that Aztec Code Reader inside my Cordova App?
// EDIT
I can Include my Plugin into App, the problem lays inside AztecReaderPlugin class and some Activity-related method. My problem is I can't open some kind of camera view through cordova. And that Camera view is my Plugin.

Sure you can
Firstly you need to declare your custom plugin in config.xml. You can found this file in res > xml folder.
<feature name="CustomPlugin">
<param name="android-package" value="com.Phonegap.CustomPlugin" />
</feature>
Then you need to implement plugin by using Java- code
public class CustomPlugin extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
throws JSONException {
if (action.equals("sayHello")){
try {
String responseText = "Hello world, " + args.getString(0);
callbackContext.success(responseText);
} catch (JSONException e){
callbackContext.error("Failed to parse parameters");
}
return true;
}
return false;
}
}
Finally we calling a plugin from javascript
function initial(){
var name = $("#NameInput").val();
cordova.exec(sayHelloSuccess, sayHelloFailure, "CustomPlugin", "sayHello", [name]);
}
function sayHelloSuccess(data){
alert("OK: " + data);
}
function sayHelloFailure(data){
alert("FAIL: " + data);
}

Related

how to disable screenshot in capacitor plugin only for few pages not for entire app

it's an ionic capacitor angular project in which I am trying to build a capacitor plugin so that I can disable screenshots only for required pages/screens.
I have used getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); within MainActivity inside onCreate() method, it works but it disables the screenshot for entire application which is not the desired outcome.
MainAcitivity.java:
public class MainActivity extends BridgeActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
add(Contacts.class);
add(Screenshot.class);
}});
}
}
Now I have capacitor plugin "screenshot-plugin" in which I have 2 methods to "SET" and "CLEAR" the flag for particular pages/screen in project.
Screenshot.java:
#NativePlugin
public class Screenshot extends Plugin {
#PluginMethod
public void echo(PluginCall call) {
String value = call.getString("value");
JSObject ret = new JSObject();
ret.put("value", value);
call.success(ret);
}
#PluginMethod
public void enableScreenshot(PluginCall call) {
try {
Activity activity = getBridge().getActivity();
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
} catch (Exception e) {
Log.e("ABC", "Exception in enableScreenshot", e);
}
JSObject ret = new JSObject();
ret.put("status", true);
call.success(ret);
}
#PluginMethod
public void disableScreenshot(PluginCall call) {
try {
Activity activity = getBridge().getActivity();
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
} catch (Exception e) {
Log.e("ABC", "Exception in disableScreenshot", e);
}
JSObject ret = new JSObject();
ret.put("status", true);
call.success(ret);
}
}
Here I get an exception that only thread which created the view can modify it.
So I tried using MainActivity activity = new MainActivity() so that I can call getWindow() method on this activity but this gives an error cannot resolve symbol even when package is imported com.abc.myapp.
Also, when I try to use getWindow() without activity inside screenshot plugin then AndroidStudio gives compilation error, using getBridge().getActivity() and then calling getWindow() method (as in code) removes compilation error but gives above exception of only MainActivity can do so.
I could write these 2 methods in MainActivity itself but then not sure how to access these methods in ionic project component.
Using plugin I can call these methods inside my component but how to make this work for only few components/pages/screens and not for the entire android application.
Please help, Thanks in advance.
I know similar questions are already there but their use case and mine are different.
You can do like this in page where you want to disable:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
And remove flag from page where you don't want:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
Note: Not 100% sure but may be it give some idea.
found the answer to this, I built my own capacitor plugin and it works fine, but there is another plugin that is already published in the capacitor community and it supports IOS too, so check this out https://github.com/capacitor-community/privacy-screen
for those of you who want to know how it worked successfully, you have to put your code like this:
#PluginMethod
public void enableScreenshot(PluginCall call) {
final Activity activity = getBridge().getActivity();
final JSObject ret = new JSObject();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
} catch (Exception e) {
Log.e("ABC", "Exception in enableScreenshot", e);
ret.put("status", false);
}
}
});
if (!ret.has("status")) {
ret.put("status", true);
} else {
call.reject("Exception in enableScreenshot");
}
call.success(ret);
}
#PluginMethod
public void disableScreenshot(PluginCall call) {
final Activity activity = getBridge().getActivity();
final JSObject ret = new JSObject();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
// Toast.makeText(activity, "Screenshot not allowed on this page.", Toast.LENGTH_SHORT);
} catch (Exception e) {
Log.e("ABC", "Exception in disableScreenshot", e);
ret.put("status", false);
}
}
});
if (!ret.has("status")) {
ret.put("status", true);
} else {
call.reject("Exception in enableScreenshot");
}
call.success(ret);
}
activity.runOnUiThread() is the hero.

Android refresh TextViews in all fragments from mainActivity

can't understand how to refresh/update all my textviews. They are located in 13 different fragments and I can't acces them how I want.
In simple Java I got a simple gameloop
//Game Loop
boolean GameLoop = true;
while(GameLoop){
CG.refresh();
}
and In main class I got something like this :
void refresh() {
Labels.MoneyLabel.setText("Money: " + CarMain.main[0]);
Labels.BoxesLabel.setText("Boxes: " + CarMain.main[2]);
}
And It All worked. Now in Android I can't update my textviews.
On Android, onCreate method made simple game loop
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
Collections();
SaveFile();
Refresh();
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
and wanted to refresh textviews like
public void Refresh(){
TextView MoneyTXT = (TextView) rootView.findViewById(R.id.MoneyText);
MoneyTXT.setText("Money: " + Main.Money[0]);
TextView MoneyPerTapTXT = (TextView) rootView.findViewById(R.id.MoneyPerTapTView);
MoneyPerTapTXT.setText("$ " + Main.Money[1] + " per tap");
TextView BoxesTXT = (TextView) rootView.findViewById(R.id.BoxesText);
BoxesTXT.setText("Boxes: " + Main.Boxes[0]);
TextView BoxesPerTapTXT = (TextView) rootView.findViewById(R.id.BoxesPerTapTView);
BoxesPerTapTXT.setText("Points " + Main.Boxes[1] + " per tap");
}
But got error, becouse Textviews are located in different layouts.
To update a Fragment from an Activity:
Assuming your Fragment has been added to a view with the id R.id.frame, you would do:
// Get current Fragment
Fragment fragment = getFragmentManager().findFragmentById(R.id.frame);
if (fragment instanceof MyFragment) { //or whatever your Fragment's name is
((MyFragment) fragment).updateTextView(); // This is a method you will have to define yourself
}
Does that make sense?
If you do not want to handle via method callback mechanism, you can try the event callback mechanism by using third party libraries like GreenRobot EventBus.
Simple example,
Define events:
public static class MessageEvent { /* Additional fields if needed */ }
Prepare subscribers:(Subscribe your activity to receive events)
Declare and annotate your subscribing method, optionally specify a thread mode:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
Register and unregister your subscriber. For example on Android, activities and fragments should usually register according to their life cycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
Post events:(On click of the fragment button post the event, activity will be notified immediately)
EventBus.getDefault().post(new MessageEvent());

UtteranceProgressListener won't call the functions

I am trying to make a speech powered app, however I have run into a major problem.
My UtteranceProgressListener Class will not call any of the given methods regardless of where I place the Speak method.
Here is my code:
This is my OnCreate Method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
voiceBtn = (Button) findViewById(R.id.startListeningBtn);
voiceBtn.setEnabled(false);
textToSpeech = new TextToSpeech(mContext,new botListener());
}
This is the OnInitListner Imeplementation
public class botListener implements TextToSpeech.OnInitListener{
#Override
public void onInit(int i) {
if(i == TextToSpeech.SUCCESS)
{
int s = textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
#Override
public void onStart(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
#Override
public void onDone(String s) {
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
}
#Override
public void onError(String s) {
Toast.makeText(getApplicationContext(),"Done Speaking",Toast.LENGTH_SHORT).show();
}
});
Log.d(TAG,String.valueOf(s));
int result = textToSpeech.setLanguage(Locale.ENGLISH);
if(result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED){
Log.e(TAG,"Language not supported");
Intent installLanguage = new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installLanguage);
}
Log.d(TAG,"Started Voice Speaker");
}
else{
Log.e(TAG,"initialization failed");
}
}
}
Now, when I press the button, the event that fires is:
public void initVoiceRecog(View v){
//Toast.makeText(mContext,"Clicked",Toast.LENGTH_SHORT).show();
Speak("hello","1");
// does some other things here after that
}
private void Speak(String text,String identifierID){
if(Build.VERSION.SDK_INT>21) {
Bundle params = new Bundle();
params.putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params, identifierID);
}
else{
// ttsMap is a HashMap
ttsMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,identifierID);
textToSpeech.speak(text,TextToSpeech.QUEUE_FLUSH,ttsMap );
}
}
My Question is, after saying hello, it does not fire the OnStart() or the OnError() or the OnDone() methods. Why is this happening?
I tried with the deprecated setOnUtteranceListner() as well, same result. It does not fire any of the methods, the Toasts don't show up.
Please tell a fix or a workaround for this.
The Devices I tried on are:
API 19 Micromax Canvas Nitro
API 21 Samsung S4
API 23(Marshmellow) ASUS Zenfone
I finally figured out why the callbacks were not working. Turns out, they were working and calling on a separate thread. So to execute the normal functionality, call the functions in the 'Activity.this.RunOnUiThread' and put this in the call back fuctions.

Android Setting Up Splash Screen(Activity) Like Iphone Part1

I have three images with me and i want them to appear on first layout xml like a splash view so that they can be viewed only once i.e that activity will be called only once when app get's installed or if app get's a new update otherwise app should always start from the Second activity, i don't know how should i begin with this :
Can any one tell me any idea how this can be done.
To show splash for only once.
Next part of this question is here
Coding will be much appreciated.
Save a flag in the Preferences when you start up the application, after you've done the welcome screen stuff. Check for this flag before you show the welcome screen. If the flag is present (in other words, if it's not the first time), don't show it.
In your activity:
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
// the code below will display a popup
String whatsNewTitle = getResources().getString(R.string.whatsNewTitle);
String whatsNewText = getResources().getString(R.string.whatsNewText);
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(whatsNewTitle).setMessage(whatsNewText).setPositiveButton(
R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Try this :
public class MainActivity extends Activity {
private Thread mSplashThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
final MainActivity sPlashScreen = this;
mSplashThread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(4000);
}
} catch (InterruptedException ex) {
}
finish();
Intent intent = new Intent();
intent.setClass(sPlashScreen, StartNewActivity.class);// <-- Activity you want to start after Splash
startActivity(intent);
}
};
mSplashThread.start();
} catch (Exception e) {
}
}
#Override
public boolean onTouchEvent(MotionEvent evt) {
try {
if (evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized (mSplashThread) {
mSplashThread.notifyAll();
}
}
} catch (Exception e) {
}
return true;
}
}
you put an Image in splash.xml to show
to do this you have to detect the first launch of your application. To do so you can store a boolean value as #Nirav suggested.
And for the splash screen, You can consider using Fragments and ViewPager to create an activity which will only be shown for the first time

Parse.com Android API and Android Dialog

I have placed the parse method inside onCreate method. But my problem is how to show the Android Loading... Dialog??
Parse.initialize(this, "a", "b");
ParseQuery query = new ParseQuery("Category");
query.findInBackground(new FindCallback() {
#Override
public void done(List<ParseObject> catObjects, ParseException arg1) {
Log.d("Catlength", String.valueOf(catObjects.size()));
for(int i =0; i<catObjects.size(); i++){
Log.d("lengthName"+String.valueOf(i), String.valueOf(catObjects.get(i).getInt("Id")));
Category category = new Category();
category.Name= catObjects.get(i).getString("CatName");
category.id= catObjects.get(i).getInt("Id");
categories.add(category);
}
if(categories.size()>0){
setListAdapter(new CategoryArrayAdapter(CategoryListActivity.this, R.layout.row_category, categories));
}
else{
Toast.makeText(CategoryListActivity.this, "Our servers are busy. Hit refresh..", 3000).show();
}
}
});
Everything works fine in the above code but I couldn't figure out how to show the Dialog.
I'm unable to use AsycTask also as parse sdk invokes its own thread in the background and before the findInBackground execution finishes, the doInBackground completes the Asyc thread. That's why I invoked it in the main thread.
As the result I always get no results in my ArrayList.
Can someone please enlighten me.
I was in the same situation regarding the progress dialog, tried a few tricks and finally just declared a ProgressDialog class member:
protected ProgressDialog proDialog;
then created two methods:
protected void startLoading() {
proDialog = new ProgressDialog(this);
proDialog.setMessage("loading...");
proDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
proDialog.setCancelable(false);
proDialog.show();
}
protected void stopLoading() {
proDialog.dismiss();
proDialog = null;
}
and called startLoading() before the background operation and stopLoading()
inside the background operation after I got the the results.
startLoading();
ParseUser.logInInBackground(userName.getText().toString(), hashedPass, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
Log.d(Constants.TAG, "User Loged in.");
ParseManager.sCurrentUser = user;
stopLoading();
finish();
} else {
stopLoading();
invalidCreds();
}
}
});
if you want to use AsyncTask don't call findInBackground() you can use find().
you can check it out in the api https://parse.com/docs/android/api/com/parse/ParseQuery.html#find()
hope this helps.
It's easy to get the progress of both uploads and downloads using ParseFile by passing a ProgressCallback to saveInBackground and getDataInBackground. For example:
byte[] data = "Working at Parse is great!".getBytes();
ParseFile file = new ParseFile("resume.txt", data);
file.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
// Handle success or failure here ...
}
}, new ProgressCallback() {
public void done(Integer percentDone) {
// Update your progress spinner here. percentDone will be between 0 and 100.
}
});

Categories