(Background: all I want is a unique and persistent Google Play identifier for the user. (even after uninstalls, or on different devices) This is the only reason I am doing this.)
I am using Cordova. This is my main activity.
Problem: the onConnected function never runs. I am able to sign in fine, however. (I can see the sign in window, the sign in circle, and everything else) but it just never runs.
NOTE: onConnectionFailed runs once, with a SIGN_IN_REQUIRED statusCode.
package com.myapp;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.games.Players;
import com.google.android.gms.games.Games;
import android.os.Bundle;
import org.apache.cordova.*;
import android.util.Log;
public class MyApp extends CordovaActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String LOGTAG = "GooglePlayServices";
// Client used to interact with Google APIs.
private GoogleApiClient mGoogleApiClient;
private CordovaActivity activity;
boolean mResolvingError;
#Override public void onCreate (Bundle savedInstanceState) {
activity = this;
super.onCreate (savedInstanceState);
super.init ();
mGoogleApiClient = new GoogleApiClient.Builder (this)
.addConnectionCallbacks (this)
.addOnConnectionFailedListener (this)
.addApi (Games.API)
.addScope(Games.SCOPE_GAMES)
.build ();
mGoogleApiClient.connect ();
super.loadUrl(Config.getStartUrl());
}
#Override public void onConnectionFailed (ConnectionResult result) {
if (mResolvingError) return;
if (!result.hasResolution()) {mResolvingError = true; return;}
Log.d (LOGTAG, result.toString());
try {
mResolvingError = true;
result.startResolutionForResult (this, result.getErrorCode());
} catch (SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect ();
}
}
#Override public void onConnected (Bundle connectionHint) {
// This never runs... this is the most critical part. I need the player ID!
String playerId = Games.Players.getCurrentPlayerId (mGoogleApiClient);
Log.w (LOGTAG, playerId);
}
// I saw this one with an #Override in others' code, but it won't compile if I add that.
public void onDisconnected () {}
protected void onStart () {super.onStart (); mGoogleApiClient.connect ();}
protected void onStop () {
super.onStop ();
if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect ();
}
protected void onActivityResult (int requestCode, int responseCode, Intent intent) {
if (!mGoogleApiClient.isConnecting()) mGoogleApiClient.connect ();
}
public void onConnectionSuspended (int cause) {mGoogleApiClient.connect ();}
}
"Your Oauth2 client CAN NOT be created from Google APIs Console, it MUST be created from the Google Play UI."
Related
I am working on QR code scanner App which takes user credentials and scan QR code and store User credentials with the content on QR code.
Since, I am beginner on working with Android App Development and hence, facing several issues such as:
(i) While opening camera permissions in App, it doesn't start automatically.I need to restart the app to open the camera to start QR code scanning.
Is there any possibility through which my app opens camera without taking permission from user. I have seen many apps doing so.
Or is there any modifications I can do to my QR scanner Java file so my camera works on runtime permission :qrscan.java
package com.example.android.loginapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.android.loginapp.R;
import com.google.android.gms.common.wrappers.PackageManagerWrapper;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import java.io.IOException;
public class qrscan extends AppCompatActivity {
private Button takePictureButton;
SurfaceView surfaceView;
CameraSource cameraSource;
TextView textView;
BarcodeDetector barcodeDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.qrcode);
super.onCreate(savedInstanceState);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
textView=(TextView)findViewById(R.id.textView);
barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
cameraSource = new CameraSource.Builder(this,barcodeDetector).setRequestedPreviewSize(640,480).build();
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(qrscan.this, new String[] {Manifest.permission.CAMERA}, 0);
return;
}
try {
cameraSource.start(holder);
}catch(IOException e){
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> qrCodes = detections.getDetectedItems();
if(qrCodes.size()!=0){
textView.post(new Runnable() {
#Override
public void run() {
Vibrator vibrator=(Vibrator)getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
textView.setText(qrCodes.valueAt(0).displayValue);
}
});
}
}
});
}
}
(ii) My second issue is that: I want to store credentials of user with the QR code. But I lack knowledge of database and all those stuff.
Is there any easy way through which I can store such data ?
Something like storing data on google cloud.
I have already seen similar questions on stack overflow but none of them solves my issue.
This question is similar but doesn't help : surface view does not show camera after i gave permission
You need to check for permission to camera in activity where you have qr reader functionality before you start using it. If application do not have permission to that device you push it for ask again or just ignore it and let user know about it by message.
Example code
private void permissionAsk(String permission){
int grant = ContextCompat.checkSelfPermission(this, permission);
if (grant != PackageManager.PERMISSION_GRANTED) {
String[] permission_list = new String[1];
permission_list[0] = permission;
ActivityCompat.requestPermissions(this, permission_list, 1);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
String permission = Manifest.permission.CAMERA;
permissionAsk(permission);
permissionAsk(Manifest.permission.RECORD_AUDIO);
permissionAsk(Manifest.permission.WRITE_EXTERNAL_STORAGE);
You can easly find more solutions like that almost ready to go.
In an android application that I am developing Im using a thread, and to make sure I dont get the "java.lang.IllegalStateException: System services not available to Activities before onCreate()" I use a boolean called donecreate. Problem is that Android studio says I have a "java.lang.NullPointerException at picLoop.run(picLoop.java:24)"
Code main class:
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
public class main extends Activity {
public Boolean donecreate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new eyeCanvas(this));
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
docreate();
}
public void docreate(){
donecreate = true;
}
public void checkHead(){
AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
if(am.isWiredHeadsetOn()){
Toast.makeText(getApplicationContext(), "HEADPHONES", Toast.LENGTH_LONG).show();
}
}
}
Code: pic loop
import android.graphics.Canvas;
//**Threading
public class picLoop extends Thread {
private eyeCanvas eye;
private main main = new main();
public picLoop(eyeCanvas eye) {
this.eye = eye;
}
#Override
public void run(){
Canvas c = null;
while(true) {
if(main.donecreate){ //<-- where error is
main.checkHead();
}
try {
// head.onCreate(Bundle savedInstanceState);
c = eye.getHolder().lockCanvas();
synchronized (eye.getHolder()) {
eye.onDraw(c);
}
} finally {
if (c != null) {
eye.getHolder().unlockCanvasAndPost(c);
}
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Also if you guys could give me feedback on how I submitted, It would help :)
You can't create activities like you're trying to do. You can NEVER EVER do 'new Activity()', as the activity needs to be launched by the system to get set up properly and go through its lifecycle as intended.
So remove the line private main main = new main();.
To do what you're trying, make the boolean a static variable.
Change
public Boolean donecreate;
to
public static Boolean donecreate;
Then you can access it like you're trying to do, without creating an instance of main Activity.
There are a large number of things wrong with the assumptions you're making. Firstly, if your Thread requires your Activity to be created, don't start it until your Activity is created. Manage the lifecycle of this object within the Activity itself, i.e.:
#Override
public void onStart() {
super.onStart();
// Start your work here
}
#Override
public void onStop() {
super.onStop();
// Stop your work here
}
Secondly, please don't use the static access approach being recommended -- that makes the assumption that there is only one Activity instance (which is wrong immediately on a configuration change, and/or if you start another instance of that Activity in the task). And even if that assumption were true, you would need to set it back to false in onDestroy() (still, don't do that).
try setting donecreate to false initially
public class main extends Activity {
public Boolean donecreate = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
....
You can request system service on application context, look at this answer.
So create a static variable in application class, initialize it like instance = this; in onCreate of Application class and then you'll be able to get app context whenever you want.
In a barebones Android application, I want to call a method in the MainActivity instance, from an asynchronous callback in the instance of another class. Why does Java force me to call a static method in the class, rather than a non-static method in the instance itself?
My app has a MainActivity class and a TextToSpeech (TTS) class. From the main activity, I instantiate the class, passing a pointer to the MainActivity instance. Instantiation of the TTS engine is an asynchronous operation. I cannot interact with the TTS instance until it has triggered an onInit() method.
Below is code that works. However, I had imagined that I would be able to call a non-static method in the MainActivity instance, and this appears not to be possible. The code below uses a static call to the MainActivity class itself, so no instance variables are available.
Here are the changes I made to a basic Hello World application in Android Studio.
//MainActivity.java
package com.example.callback;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends ActionBarActivity {
private static TTS tts; // apparently this has to be static
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onResume() {
super.onResume();
tts = new TTS();
Log.d("onResume", this.toString());
// D/Main﹕ com.example.callback.MainActivity#4a014e50
tts.init(this);
}
// Apparently this method has to be static
public static void ttsReady() {
tts.speakText("Hello world");
}
}
Custom class.
// TTS.java
package com.example.callback;
import android.app.Activity;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import java.util.HashMap;
import java.util.Locale;
public class TTS implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
private Activity activity;
public void init(Activity currentActivity) {
activity = currentActivity;
Context context = activity.getApplicationContext();
tts = new android.speech.tts.TextToSpeech(context, this);
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
Log.d("onInit", activity.toString());
// D/onInit﹕ com.example.callback.MainActivity#4a014e50
// activity.ttsReady();
// The line above does not compile. ttsReady() is not recognized as a
// method of activity, regardless of whether the tts variable and the
// ttsReady() method in the MainActivity class are made static or not,
// Making the activity variable static here has no effect either.
// The commented line below throws Error:(31, 35)
// error: non-static method toString() cannot be referenced from a static context
// So presumably MainActivity is a static variable.
// Log.d("onInit", MainActivity.toString())
// This works, if the tts variable and the ttsReady() method in the
// MainActivity class are made static. Is there a non-static alternative?
MainActivity.ttsReady();
}
}
// Deprecated signature for speak() used for compatibility with API 20
// and earlier
public void speakText(String toSpeak) {
int mode = android.speech.tts.TextToSpeech.QUEUE_FLUSH;
// Object hashMap = null; // Causes a "no suitable method error".
// How is HashMap null not the same as Object null? Using just plain null
// instead of hashMap also works with no problems.
HashMap hashMap = null;
tts.speak(toSpeak, mode, hashMap);
}
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
Log.d("onInit", activity.toString());
((MainActivity)activity).ttsReady();
}
}
You are not referring to the instance of MainActivity when you say MainActivity.ttsReady(). That is why you can only access static methods. You need to make a call to the instance itself which you have stored in the activity variable.
Edit:
For a complete solution based on what you're trying to accomplish, I would probably set it up this way:
// TTSActivity.java
public abstract class TTSActivity extends Activity implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tts = new TextToSpeech(this, this);
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
ttsReady();
}
}
public void speakText(String toSpeak) {
int mode = android.speech.tts.TextToSpeech.QUEUE_FLUSH;
tts.speak(toSpeak, mode, null);
}
protected TextToSpeech getTts() {
return tts;
}
protected abstract void ttsReady();
}
then MainActivity becomes:
// MainActivity.java
public class MainActivity extends TTSActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void ttsReady() {
speakText("Hello world");
}
}
Any Activity you want to use TTS in, all you have to do is extend TTSActivity and implements ttsReady().
As you can see, this is much more concise and easier to understand. However, your exact implementation will of course be dependent upon all the requirements you have in your particular application.
#zaventh's answer helped me to realize that a Java instance needs to be cast to the right class or interface for its methods to be found in the inheritance hierarchy. I have now rewritten my barebones project to include an interface that declares the ttsReady() method.
Here is the solution that allows me to access the methods of the MainActivity instance in a generic way.
TTSUser Interface
package com.example.callback;
interface TTSUser {
void ttsReady();
}
MainActivity
package com.example.callback;
import android.app.Activity;
import android.os.Bundle;
// TTUser Interface ensures the existence of the ttsReady() method in every instance
public class MainActivity extends Activity implements TTSUser {
private TTS tts; // non-static
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onResume() {
super.onResume();
tts = new TTS();
tts.init(this);
}
public void ttsReady() { // non-static
tts.speakText("Hello world");
}
}
TTS Class
package com.example.callback;
import android.app.Activity;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import java.util.Locale;
public class TTS implements TextToSpeech.OnInitListener {
private TextToSpeech tts;
private TTSUser activity;
// Use the TTSUser interface in the signature
public void init(TTSUser activity) {
this.activity = activity;
// Cast to generic Activity, to access .getApplicationContext()
Context context = ((Activity) activity).getApplicationContext();
tts = new android.speech.tts.TextToSpeech(context, this);
}
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.UK);
activity.ttsReady(); // accessible through the TTSUser interfaceg
}
}
// Deprecated signature for speak() used for compatibility with API 20
// and earlier
public void speakText(String toSpeak) {
int mode = android.speech.tts.TextToSpeech.QUEUE_FLUSH;
tts.speak(toSpeak, mode, null);
}
}
I've defined a remote service in an Android Library project using AIDL. The service is supposed to simply increment an int. I try to bind to it from another project, an application using the library. The application's call to bindService(...) always returns false. What am I doing wrong?
The main activity of the application project:
MainActivity.java
package com.example.serviceusera;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.example.service.IncService;
import com.example.service.IncServiceConnection;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private IncServiceConnection mConnection;
private int mCount = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
try {
mConnection = bindService();
} catch (RemoteException e) {
Log.e(TAG, "Failed to bind service", e);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
}
private IncServiceConnection bindService() throws RemoteException {
IncServiceConnection connection = new IncServiceConnection();
Intent service = new Intent(IncService.class.getName());
boolean bound = bindService(service, connection, Context.BIND_AUTO_CREATE);
Log.d(TAG, "bindService() = " + bound);
if (bound) {
return connection;
} else {
throw new RemoteException("Failed to bind service");
}
}
private void init() {
// Show the current value of the counter
final EditText text = (EditText) findViewById(R.id.editText1);
text.setText(Integer.toString(mCount));
// Set button to increment counter
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
mCount = mConnection.inc(mCount);
text.setText(Integer.toString(mCount));
} catch (RemoteException e) {
Log.e(TAG, "Failed to use service", e);
}
}
});
}
}
The library project:
IIncService.aidl
package com.example.service;
interface IIncService {
int inc(in int i);
}
IncService.java
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class IncService extends Service {
private final IIncService.Stub mBinder = new IIncService.Stub() {
#Override
public int inc(int i) throws RemoteException {
return i + 1;
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
IncServiceConnection.java
package com.example.service;
import android.content.ComponentName;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
public class IncServiceConnection implements ServiceConnection {
private IIncService mService;
public int inc(int i) throws RemoteException {
return mService.inc(i);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IIncService.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
}
I've added the service to the library's manifest:
AndroidManifest.xml
...
<application
...
<service
android:name="com.example.service.IncService"
android:process=":remote" >
</service>
</application>
...
and enabled mainfest merging in the application:
project.properties
...
manifestmerger.enabled=true
I've tried Your code using IntelliJ Idea 13 and have found the issue.
Firstly, I ensured that:
Library project is exported;
Application project has Enable manifest merging on under Android Compiler properties;
Using that configuration it didn't work and I've observed Unable to start service Intent.
The issue here is in incorrect Intent creation. Seems that class name You obtain by IncService.class.getName() doesn't specify the component completely (if logs checked it looks like so, because intent contains only class name, but package name is missed). So, to specify component properly, I've used another way:
final Intent service = new Intent(this, IncService.class);
And it worked fine.
Instead of binding Ibinder, try using binding with Handler. I have recently done an application the way you did and I could not figure out the fault. But working with Messager made things easier.
Instead of return binder object. It returns message obj. Here is the reference.
Source: Android Remote Bound Services
I'm trying to change between activities in my Android app (2.1-update1), but it doesn't work.
Any suggestions?
The only thing that happens when I debug the app is that it stops on this part of the code in Instrumentation.java:
public void waitForIdle() {
synchronized (this) {
while (!mIdle) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
}
Eclipse says that it is in Thread 1 on
Instrumentation.checkStartActivityResult(int, Object) line: 1537. If I
resume the app, the next stop is in ZygoteInit.java trying to run
Throwable cause = ex.getCause(); ... Eclipse says
ZygoteInit$MethodAndArgsCaller.run() line: 864.
Here is the source code:
HappyHomes.java
package com.example.app;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class HappyHomes extends Activity {
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button login = (Button) findViewById(R.id.btnLogin);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ProgressDialog laddRuta = ProgressDialog.show(HappyHomes.this, "",
"Loggar in, vänligen vänta...", true);
Intent myIntent = new Intent(view.getContext(), Kategorier.class);
myIntent.
startActivity(myIntent);
}
});
}
}
Kategorier.java
package com.example.app;
import android.app.Activity;
import android.os.Bundle;
public class Kategorier extends Activity {
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.kategorier);
}
}
Thanks for helping!
Make sure that Kategorier is registered in your AndroidManifest.xml file.
Change myIntent.startActivity(myIntent); to HappyHomes.this.startActivity(myIntent);
There is no any startActivity() method in Intent class . you must be doing wrong.
just write startActivity(myIntent)
All the Services, Broadcast Receivers and Activites must be declared in manifest file.