Google Drive API implementation Xamarin Android - xamarin

Our application should have the functionality to save Application files to Google Drive. Of course, using the local configured account.
From Android API i tried to figure out some clue. But android API with Xamarin implementation seems very tough for me.
I have installed Google Play Services- Drive from Xamarin Components but there are no examples listed from which we can refer the flow and functionality.

The basic steps (see the link below for full details):
Create GoogleApiClient with the Drive API and Scope
Try to connect (login) the GoogleApiClient
The first time you try to connect it will fail as the user has not selected a Google Account that should be used
Use StartResolutionForResult to handle this condition
When GoogleApiClient is connected
Request a Drive content (DriveContentsResult) to write the file contents to.
When the result is obtained, write data into the Drive content.
Set the metadata for the file
Create the Drive-based file with the Drive content
Note: This example assumes that you have Google Drive installed on your device/emulator and you have registered your app in Google's Developer API Console with the Google Drive API Enabled.
C# Example:
[Activity(Label = "DriveOpen", MainLauncher = true, Icon = "#mipmap/icon")]
public class MainActivity : Activity, GoogleApiClient.IConnectionCallbacks, IResultCallback, IDriveApiDriveContentsResult
{
const string TAG = "GDriveExample";
const int REQUEST_CODE_RESOLUTION = 3;
GoogleApiClient _googleApiClient;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate
{
if (_googleApiClient == null)
{
_googleApiClient = new GoogleApiClient.Builder(this)
.AddApi(DriveClass.API)
.AddScope(DriveClass.ScopeFile)
.AddConnectionCallbacks(this)
.AddOnConnectionFailedListener(onConnectionFailed)
.Build();
}
if (!_googleApiClient.IsConnected)
_googleApiClient.Connect();
};
}
protected void onConnectionFailed(ConnectionResult result)
{
Log.Info(TAG, "GoogleApiClient connection failed: " + result);
if (!result.HasResolution)
{
GoogleApiAvailability.Instance.GetErrorDialog(this, result.ErrorCode, 0).Show();
return;
}
try
{
result.StartResolutionForResult(this, REQUEST_CODE_RESOLUTION);
}
catch (IntentSender.SendIntentException e)
{
Log.Error(TAG, "Exception while starting resolution activity", e);
}
}
public void OnConnected(Bundle connectionHint)
{
Log.Info(TAG, "Client connected.");
DriveClass.DriveApi.NewDriveContents(_googleApiClient).SetResultCallback(this);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_RESOLUTION)
{
switch (resultCode)
{
case Result.Ok:
_googleApiClient.Connect();
break;
case Result.Canceled:
Log.Error(TAG, "Unable to sign in, is app registered for Drive access in Google Dev Console?");
break;
case Result.FirstUser:
Log.Error(TAG, "Unable to sign in: RESULT_FIRST_USER");
break;
default:
Log.Error(TAG, "Should never be here: " + resultCode);
return;
}
}
}
void IResultCallback.OnResult(Java.Lang.Object result)
{
var contentResults = (result).JavaCast<IDriveApiDriveContentsResult>();
if (!contentResults.Status.IsSuccess) // handle the error
return;
Task.Run(() =>
{
var writer = new OutputStreamWriter(contentResults.DriveContents.OutputStream);
writer.Write("Stack Overflow");
writer.Close();
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.SetTitle("New Text File")
.SetMimeType("text/plain")
.Build();
DriveClass.DriveApi
.GetRootFolder(_googleApiClient)
.CreateFile(_googleApiClient, changeSet, contentResults.DriveContents);
});
}
public void OnConnectionSuspended(int cause)
{
throw new NotImplementedException();
}
public IDriveContents DriveContents
{
get
{
throw new NotImplementedException();
}
}
public Statuses Status
{
get
{
throw new NotImplementedException();
}
}
}
Ref: https://developers.google.com/drive/android/create-file

Related

How to implement Play Install Referrer API in Android?

I want to implement Play Install Referrer API and I found document and I read that but I have have some confusion. First I have implemented all code provided by google. But I want to know which type of url I need to create so that user can click on link and go to play store and install my app and then I get the referral detail..
I use this code:
InstallReferrerClient mReferrerClient;
mReferrerClient = newBuilder(this).build();
mReferrerClient.startConnection(this);
#Override
public void onInstallReferrerSetupFinished ( int responseCode){
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established
/* ReferrerDetails response = null;
try {
response = mReferrerClient.getInstallReferrer();
response.getInstallReferrer();
response.getReferrerClickTimestampSeconds();
response.getInstallBeginTimestampSeconds();
} catch (RemoteException e) {
e.printStackTrace();
}*/
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection could not be established
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected () {
}
But which type of link I create so user go to play store and after install play store referral api give me data..
Sample url - "https://play.google.com/store/apps/details?id=com.dummy.app&referrer=referralCode%3D311566%26source%3DFacebook+App"
When using the Google Play Referrer API -
InstallReferrerClient mReferrerClient;
mReferrerClient = newBuilder(this).build();
mReferrerClient.startConnection(this);
#Override
public void onInstallReferrerSetupFinished ( int responseCode){
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established
/* ReferrerDetails response = null;
try {
response = mReferrerClient.getInstallReferrer();
response.getInstallReferrer();
response.getReferrerClickTimestampSeconds();
response.getInstallBeginTimestampSeconds();
} catch (RemoteException e) {
e.printStackTrace();
}*/
// End the connection once you get the data
referrerClient.endConnection();
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection could not be established
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected () {
}
getInstallReferrer()
will return String 'referralCode=311566&source=Facebook App'
play install referral library i wants to describe this in simple wording, being a developer you wants to know about these elements how much time you app bundle take to install on the user devices from play store, and referral url , referral click time and many others elements , google make it easy for you know you have to use play install referral library for this purpose.
add this dependency
implementation 'com.android.installreferrer:installreferrer:1.1'
you can follow the guidelines from here:
play installer referral guidelines
declare this variable in any java activity
InstallReferrerClient referrerClient;
in on create method use this code below :
referrerClient = InstallReferrerClient.newBuilder(this).build();
referrerClient.startConnection(new InstallReferrerStateListener() {
#Override
public void onInstallReferrerSetupFinished(int responseCode) {
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established.
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app.
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection couldn't be established.
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
inside onInstallReferrerSetupFinished stabled you can get these data easily,you code will be after that like this
ReferrerDetails response = null;
try {
response = referrerClient.getInstallReferrer();
} catch (RemoteException e) {
e.printStackTrace();
}
String referrerUrl = response.getInstallReferrer();
long referrerClickTime = response.getReferrerClickTimestampSeconds();
long appInstallTime = response.getInstallBeginTimestampSeconds();
boolean instantExperienceLaunched = response.getGooglePlayInstantParam();
whole code will be like this
referrerClient = InstallReferrerClient.newBuilder(this).build();
referrerClient.startConnection(new InstallReferrerStateListener() {
#Override
public void onInstallReferrerSetupFinished(int responseCode) {
switch (responseCode) {
case InstallReferrerClient.InstallReferrerResponse.OK:
// Connection established.
ReferrerDetails response = null;
try {
response = referrerClient.getInstallReferrer();
} catch (RemoteException e) {
e.printStackTrace();
}
String referrerUrl = response.getInstallReferrer();
long referrerClickTime = response.getReferrerClickTimestampSeconds();
long appInstallTime = response.getInstallBeginTimestampSeconds();
boolean instantExperienceLaunched = response.getGooglePlayInstantParam();
break;
case InstallReferrerClient.InstallReferrerResponse.FEATURE_NOT_SUPPORTED:
// API not available on the current Play Store app.
break;
case InstallReferrerClient.InstallReferrerResponse.SERVICE_UNAVAILABLE:
// Connection couldn't be established.
break;
}
}
#Override
public void onInstallReferrerServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});

Turning Bluetooth Tethering On in Xamarin.Android

I'm currently trying to add some Bluetooth functionality to my app. I want to be able to change the Bluetooth Tethering on or off, as well as check its status.
I found the Java code on StackOverflow: How to check Bluetooth tethering status programmatically in Android
I have translated it into C#, but I don't seem to be able to get any result.
Regardless of the tethering setting, it always shows the toast with "Tethering:false", and the setBluetoothTethering doesn't change anything.
Any idea what I'm missing?
Here's my code:
[...]
try
{
Class classBluetoothPan = Class.ForName("android.bluetooth.BluetoothPan");
Method mBTPanConnect = classBluetoothPan.GetDeclaredMethod("connect", Class.FromType(typeof(BluetoothDevice)));
Constructor BTPanCtor = classBluetoothPan.GetDeclaredConstructor(Class.FromType(typeof(Context)), Class.FromType(typeof(IBluetoothProfileServiceListener)));
BTPanCtor.Accessible = true;
Java.Lang.Object BTSrvInstance = BTPanCtor.NewInstance(Activity, new BTPanServiceListener(Activity));
Method isTetheringOnMethod = classBluetoothPan.GetDeclaredMethod("isTetheringOn", null);
var isTetheringOn = isTetheringOnMethod.Invoke(BTSrvInstance);
Toast.MakeText(Activity, "Tethering:" + isTetheringOn, ToastLength.Short).Show();
Method setBluetoothTetheringMethod = classBluetoothPan.GetDeclaredMethod("setBluetoothTethering", new Class[1] { Class.FromType(typeof(bool)) });
setBluetoothTetheringMethod.Invoke(BTSrvInstance, true);
// tether = !tether;
}
catch (ClassNotFoundException e)
{
e.PrintStackTrace();
}
catch (Java.Lang.Exception e)
{
e.PrintStackTrace();
}
[...]
public class BTPanServiceListener : Java.Lang.Object, IBluetoothProfileServiceListener
{
private Activity _activity;
public BTPanServiceListener(Activity activity)
{
_activity = activity;
}
public void OnServiceConnected([GeneratedEnum] ProfileType profile, IBluetoothProfile proxy)
{
// throw new NotImplementedException();
}
public void OnServiceDisconnected([GeneratedEnum] ProfileType profile)
{
// throw new NotImplementedException();
}
}
I figured out how to enable Bluetooth tethering via setBluetoothTethering.
I wrote an entire blog about this
You can find the final code here
I assume that isTetheringOn works in the same way

How to send OnActivityResult To a specific page in xamarin forms

I am using a custom button renderer for google sign In in xamarin forms page its working fine I get the signin resultin MainActivity Now i want to send this data from MainActivity and AppDelegate to the Particular page in Xamarin Forms.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 9001)
{
Utilities.Configuration.UpdateConfigValue(Utilities.Constants.loggedInflag,string.Empty);
GoogleSignInResult result = Android.Gms.Auth.Api.Auth.GoogleSignInApi.GetSignInResultFromIntent(data);
if (result.IsSuccess)
{
GoogleSignInAccount acct = result.SignInAccount;
var token = acct.IdToken;
//I wan to send the 'accnt' to a Page in xamarin forms
}
else
{
//Signin Failure send response to Page in xamarin forms
}
}
}
Xamarin.Forms runs only in one Activity on Android. So if your url request comes out in a different Activity, you have to switch back to the MainActivity before you can use the normal XF navigation.
I do this when a user opens a file associated with my app.
[Activity(Label = "LaunchFileActivity")]
public class LaunchFileActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (Intent.Data != null)
{
var uri = Intent.Data;
if (uri != null)
{
Intent i = new Intent(this, typeof(MainActivity));
i.AddFlags(ActivityFlags.ReorderToFront);
i.PutExtra("fileName", uri.Path);
this.StartActivity(i);
}
}
this.FinishActivity(0);
}
}
And in MainActivity:
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
Intent = intent;
}
protected override void OnPostResume()
{
base.OnPostResume();
if (Intent.Extras != null)
{
string fileName = Intent.Extras.GetString("fileName");
if (!string.IsNullOrEmpty(fileName))
{
// do something with fileName
}
Intent.RemoveExtra("fileName");
}
}
Xamarin forms runs on one activity, which is most like your main activity.
There are two sample projects that show you how to communicate between native and form parts of the code, which can be found here
https://github.com/xamarin/xamarin-forms-samples/tree/master/Forms2Native
https://github.com/xamarin/xamarin-forms-samples/tree/master/Native2Forms
However, to answer your question, you would do something like the following
private const int MyRequestCode = 101;
//Start activity for result
var contactPickerIntent = new Intent(Intent.ActionPick, Android.Provider.ContactsContract.Contacts.ContentUri);
context.StartActivityForResult(contactPickerIntent, MyRequestCode);
and then in your main activity (the activity that initializes your xamarin forms application (using global::Xamarin.Forms.Forms.Init(this, bundle);)
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == MyRequestCode && resultCode == Result.Ok)
{
}
}

How to detect emergency call only in Xamarin?

Is there a way to detect if the phone, at the call try moment, can only make emergency calls (using Xamarin)?
This is something platform specific. Unfortunaelty I don't know any plugin for this, so you have to use the native API in Xamarin.
On Android it is the TelephonyManager as shown here: https://stackoverflow.com/a/14355706/1489968 It's Java, but can be easily translated to C#:
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var telMng = (TelephonyManager) GetSystemService(TelephonyService);
var myPhoneStateListener = new MyPhoneStateListener();
myPhoneStateListener.ServiceStateChanged += (s, e) => Console.WriteLine("State: {0}", e);
telMng.Listen(myPhoneStateListener, PhoneStateListenerFlags.ServiceState);
}
}
public class MyPhoneStateListener : PhoneStateListener
{
public event EventHandler<ServiceState> ServiceStateChanged;
public override void OnServiceStateChanged(ServiceState serviceState)
{
base.OnServiceStateChanged(serviceState);
ServiceStateChanged?.Invoke(this, serviceState);
}
}
On iOS: Not sure if that information is available, never have seen it exposed via the SDK... (maybe add iOS tag to this question, or ask an iOS only question, answer might be in ObjC/Swift but you can translate it)
On Android: The info you are looking for is contained within the ServiceState of the phone:
var callState = new ServiceState ();
switch (callState.State) {
case PhoneState.InService:
{
var uri = Android.Net.Uri.Parse ("tel:555-2368"); // Jim Rockford's number ;-)
var intent = new Intent (Intent.ActionDial, uri);
StartActivity (intent);
break;
}
case PhoneState.EmergencyOnly:
{
Toast.MakeText (this, "Emergency Calls Only", ToastLength.Long).Show();
break;
}
case PhoneState.OutOfService:
{
Toast.MakeText (this, "Out of Service", ToastLength.Long).Show();
break;
}
case PhoneState.PowerOff:
{
Toast.MakeText (this, "Cell/Modem Power Off", ToastLength.Long).Show();
break;
}
default:
{
Toast.MakeText (this, "Should never be shown on a real device", ToastLength.Long).Show();
break;
}
}
Ref: http://developer.android.com/reference/android/telephony/ServiceState.html
For testing on the emulator, you can set the state to denied via the adb shell:
voice denied
data denied
Ref: https://developer.android.com/tools/devices/emulator.html

Android Auto - Callback when user connects mobile device

In regards to Android auto how can i get a callback when user has plugged the device into a car ? I'd like to trigger an action to occur based on when the user actually connects to android auto, is it possible ?
You should be able to get USB connection broadcast. From there you will have to write your own logic to figure out Android Auto is in foreground.
(may need to introduce a slight delay in case android auto takes time to come up. Launcher seems to be part of google play service)
Here is how I did it in my services onCreate method (right form the example code):
IntentFilter filter = new IntentFilter(CarHelper.ACTION_MEDIA_STATUS);
mCarConnectionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String connectionEvent = intent.getStringExtra(CarHelper.MEDIA_CONNECTION_STATUS);
mIsConnectedToCar = "media_connected".equals(connectionEvent);
LogHelper.i(TAG, "Connection event to Android Auto: ", connectionEvent,
" isConnectedToCar=", mIsConnectedToCar);
if(mIsConnectedToCar ) {
if(mService == null) {
bindMusicService();
if (mService != null) {
try {
initMediaMetaData();
toggleMediaPlaybackState(mService.isPlaying());
} catch (RemoteException e) {
Log.d(TAG, e.toString());
}
}
}
}
}
};
registerReceiver(mCarConnectionReceiver, filter);

Resources