Install APK by programmatically Xamarin.Forms (Android) - c#

So far my code looks like this:
1. Dowload the APK file and save it into internal storege:
Using DependencyServices
App.xaml.cs
IDownloader downloader = DependencyService.Get<IDownloader>();
protected override void OnStart(){
downloader.OnFileDownloaded+=OnFileDownloaded;
downloader.DownloadFile("http://localhost:8080/download","folder");
}
private void OnFileDownloaded(object sender,DownloadEventArgs e) {
if(e.FileSaved) {
App.Current.MainPage.DisplayAlert("XF Downloader","File Saved Successfully","Close");
} else {
App.Current.MainPage.DisplayAlert("XF Downloader","Error while saving the file","Close");
}
}
Android : AndroidDownloader.cs
[assembly: Dependency(typeof(NoguianaNucleo.Droid.AndroidDownloader))]
namespace NoguianaNucleo.Droid {
public class AndroidDownloader: IDownloader {
public event EventHandler<DownloadEventArgs> OnFileDownloaded;
public void DownloadFile(string url,string folder) {
string pathToNewFolder = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal),folder);
Directory.CreateDirectory(pathToNewFolder);
try {
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted+=new AsyncCompletedEventHandler(Completed);
string pathToNewFile = Path.Combine(pathToNewFolder,"nucleo.apk");
webClient.DownloadFileAsync(new Uri(url),pathToNewFile);
} catch(Exception ex) {
if(OnFileDownloaded!=null)
OnFileDownloaded.Invoke(this,new DownloadEventArgs(false));
}
}
private void Completed(object sender,AsyncCompletedEventArgs e) {
if(e.Error!=null) {
App.Current.MainPage.DisplayAlert("Error", e.Error.Message,"Ok");
if(OnFileDownloaded!=null)
OnFileDownloaded.Invoke(this,new DownloadEventArgs(false));
} else {
if(OnFileDownloaded!=null)
OnFileDownloaded.Invoke(this,new DownloadEventArgs(true));
}
}
}
}
2. Intall the APK file from the internal storege:
App.xaml.cs
public void OpenApk(string filepath) {
Java.IO.File file = new Java.IO.File(filepath);
Intent install = new Intent(Intent.ActionView);
// Old Approach
if(Android.OS.Build.VERSION.SdkInt<Android.OS.BuildVersionCodes.N) {
install.SetFlags(ActivityFlags.NewTask|ActivityFlags.GrantReadUriPermission);
install.SetDataAndType(Android.Net.Uri.FromFile(file),"application/vnd.android.package-archive"); //mimeType
} else {
Android.Net.Uri apkURI = Android.Support.V4.Content.FileProvider.GetUriForFile(Android.App.Application.Context,Android.App.Application.Context.ApplicationContext.PackageName+".fileprovider",file);
install.SetDataAndType(apkURI,"application/vnd.android.package-archive");
install.AddFlags(ActivityFlags.NewTask);
install.AddFlags(ActivityFlags.GrantReadUriPermission);
}
Android.App.Application.Context.StartActivity(install);
}
This last function doesn't work. I think Android.Support its not support any more.
I also tried this:
var downloadUri = Android.Net.Uri.Parse("/data/user/0/noguiana.nucleo/files/noguiana/nucleo.apk");
Intent install = new Intent(Intent.ActionInstallPackage);
install.AddFlags(ActivityFlags.GrantReadUriPermission);
install.AddFlags(ActivityFlags.GrantWriteUriPermission);
install.AddFlags(ActivityFlags.GrantPersistableUriPermission);
install.SetDataAndType(downloadUri,"application/vnd.android.package-archive");
context.StartActivity(install);
Nothing works
Do you know other way to install APK by programmatically in Xamarin.Forms (Android)?

Use PackageInstaller instead.
ActionView and ACTION_INSTALL_PACKAGE had been deprecated in API level 29.
Have you tried this solution?
Android PackageInstaller not installing APK

Related

Showing Google Admob Interstitial ad in Xamarin Forms without delay

I'm working on Xamarin forms project and i have implemented Interstitial ad on all three platforms (Google admob doesn't support UWP). Ads are working fine but they are showing with a delay of 4 to 5 seconds. All i want is to finish that delay so they can show immediately.
PCL class.
public interface IAdmobInterstitial
{
void Show(string adUnit);
}
Droid Code.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
if (_ad.IsLoaded)
_ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
}
iOS Code.
public class AdmobInterstitial : IAdmobInterstitial
{
Interstitial _adInterstitial;
public void Show(string adUnit)
{
_adInterstitial = new Interstitial(adUnit);
var request = Request.GetDefaultRequest();
_adInterstitial.AdReceived += (sender, args) =>
{
if (_adInterstitial.IsReady)
{
var window = UIApplication.SharedApplication.KeyWindow;
var vc = window.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
_adInterstitial.PresentFromRootViewController(vc);
}
};
_adInterstitial.LoadRequest(request);
}
}
Calling interstitial ad on PCL page.
DependencyService.Get<IAdmobInterstitial>().Show("(id will come here)");
Navigation.PushAsync(new Page());
Ad is showing perfectly but with a delay. I want to show the ad first and then the page.
So i just solved this.
Here is the code.
PCL Class. Add another function to your interface.
public interface IAdmobInterstitial
{
void Show(string adUnit);
void Give();
}
Droid code. Put _ad.Show() in the new function.
public class InterstitialAdListener : AdListener
{
readonly InterstitialAd _ad;
public InterstitialAdListener(InterstitialAd ad)
{
_ad = ad;
}
public override void OnAdLoaded()
{
base.OnAdLoaded();
//if (_ad.IsLoaded)
// _ad.Show();
}
}
public class AdmobInterstitial : Controls.IAdmobInterstitial
{
InterstitialAd _ad;
public void Show(string adUnit)
{
var context = Android.App.Application.Context;
_ad = new InterstitialAd(context);
_ad.AdUnitId = adUnit;
var intlistener = new InterstitialAdListener(_ad);
intlistener.OnAdLoaded();
_ad.AdListener = intlistener;
var requestbuilder = new AdRequest.Builder().AddTestDevice("302E90D530B2193F59FDD7F22A11B45A");
_ad.LoadAd(requestbuilder.Build());
}
public void Give()
{
if (_ad.IsLoaded)
_ad.Show();
}
}
Now, call the function Show() in the constructor of your MainPage in PCL and call the function Give() when you press the button for the next page.
public MainPage()
{
InitializeComponent();
DependencyService.Get<IAdmobInterstitial>().Show("ca-app-pub-3940256099942544/1033173712");
}
private void button_Clicked(object sender, EventArgs e)
{
DependencyService.Get<IAdmobInterstitial>().Give();
Navigation.PushAsync(new Percentage());
}
This is only for Android. Same goes for iOS as well.
I hope it helps the other programmers. :)

Unity Android Screen Capture Plugin

I'm in the process of developing a custom Unity Plugin (Android) that allows the Unity application to record the screen. I've looked at several existing Unity plugins and none seem to either work or do exactly what I'm needing. I was able to get a VERY simple Android plugin (.jar) built and loaded into Unity using this nice tutorial.
To be clear... this is my very first attempt at creating a Unity plugin.
My problem is that when I extend the Activity my plugin fails to function. When debugging, the log cat doesn't enter the onCreate() method and the Log.d() message isn't thrown. Any help on identifying if the below source code is valid would be great. This code is nothing like the tutorial I watched. Much more involved.
BTW, I first built the below code in Android Studio and ran on a device to make sure the code actually performed as expected. It did. I then took the code from that initial test and started developing the Unity plugin below based on the video tutorial and other resources.
Here's my Android Java code that builds the classes.jar file with no build errors.
package lib.rrpartners.com.unityscreencaptureplugin;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.Surface;
import java.io.IOException;
public class ScreenCapturePlugin extends Activity {
private static final String TAG = "ScreenCapturePlugin";
private static final int REQUEST_CODE = 1000;
private int mScreenDensity;
private MediaProjectionManager mProjectionManager;
private static final int DISPLAY_WIDTH = 1440;
private static final int DISPLAY_HEIGHT = 2560;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaProjectionCallback mMediaProjectionCallback;
private ToggleButton mToggleButton;
private MediaRecorder mMediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int REQUEST_PERMISSIONS = 10;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
public String getText() {
return "Some text here";
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.d("OverrideActivity", "onCreate called!");
super.onCreate(savedInstanceState);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
mToggleButton.setChecked(false);
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
public void startScreenRecording() {
initRecorder();
startScreenRecording();
if (mMediaProjection == null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
return;
}
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("MainActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
private void initRecorder() {
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(Environment
.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS) + "/video.mp4");
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(3000000);
mMediaRecorder.setVideoFrameRate(30);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private class MediaProjectionCallback extends MediaProjection.Callback {
#Override
public void onStop() {
if (mToggleButton.isChecked()) {
mToggleButton.setChecked(false);
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Recording Stopped");
}
mMediaProjection = null;
stopScreenSharing();
}
}
private void stopScreenSharing() {
mMediaRecorder.stop();
mMediaRecorder.reset();
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
//mMediaRecorder.release(); //If used: mMediaRecorder object cannot
// be reused again
destroyMediaProjection();
}
#Override
public void onDestroy() {
super.onDestroy();
destroyMediaProjection();
}
private void destroyMediaProjection() {
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
Log.i(TAG, "MediaProjection Stopped");
}
}
Here's my Android Manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="lib.rrpartners.com.unityscreencaptureplugin">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application android:allowBackup="true" android:label="#string/app_name"
android:supportsRtl="true">
</application>
</manifest>
Unity C# Code
frameCount = GameObject.Find("FrameCount").GetComponent<Text>();
using (AndroidJavaClass cls_UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject obj_Activity = cls_UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
obj_Activity.CallStatic("onCreate");
}
}

Windows service file listener only listens when debugging

First the code:
public partial class Watcher : ServiceBase
{
private const string PathToFolder = #"D:\print\";
public Watcher()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
private void fileWatcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.Name != "test.txt")
{
return;
}
using (var r = new StreamReader(e.FullPath))
{
var json = r.ReadToEnd();
dynamic tempTest = JsonConvert.DeserializeObject(json);
const string filename = PathToFolder + "textParsed.txt";
if (File.Exists(filename))
{
File.Delete(filename);
}
using (var file = File.CreateText(filename))
{
file.WriteLine(tempTest.Name.ToString());
}
}
}
}
If there are changes to the text.txt file I'm suppose to parse the content of that text file and create another file. If I attach VS to the service and debug the service, the event gets fired, but when running normally, nothing happens.
The installer has LocalSystem privileges and that's pretty much all the changes I've made... Should be pretty straight forward, but somehow isn't.

Windows Phone 8.1 Currency converter Json

I got a school project. I have to make a currency converter and I got stuck. I found something on the Code Project web site, but I am new at this and I do not really know how to implement it in my project.
I tried something like `
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
class WebClient
{
internal string DownloadString(string url)
{
throw new NotImplementedException();
url = "https://openexchangerates.org/api/latest.json?app_id=ae11142304694b10a1dbf2d25933a333";
var currencyRates = _download_serialized_json_data<App9.CurrencyRates>(url);
}
}
public static T _download_serialized_json_data<T>(string url) where T : new()
{
var w = new WebClient();
{
//using (var w = new WebClient()) {
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
json_data = w.DownloadString(url);
}
catch (Exception) { }
// if string with JSON data is not empty, deserialize it to class and return its instance
return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
}
}
private void comboBoxTo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void convertButton_Click(object sender, RoutedEventArgs e)
{
if (amountTb.Text == string.Empty)
{
afisareTb.Text = "Scrieti o valoare";
}
else
{
var currencyRates = _download_serialized_json_data<CurrencyRates>("https://openexchangerates.org/api/latest.json?app_id=YOUR_APP_ID ");
}
}
}
`
I do not have any errors, it is just that, when I press on converter button from my app, nothing happens.

Why doesn't my Windows Store (Metro) app appear in the Share Pane?

I have made my app a Share Target (and Source), and I can successfully Share my app's content with other apps, but when I am in another app, like Mail or IE for example, I cannot share their content with my app because it doesn't appear in the Share Pane as an available Share Target app.
I have read and followed the MSDN documentation, checked out the samples, and have also setup the Share Target Declaration in the Package.AppXManifest file.
Why, and how can I fix this?
C# Code-behind:
ShareOperation shareOperation;
private string sharedDataTitle;
private string sharedDataDescription;
private string shareQuickLinkId;
private string sharedText;
private Uri sharedUri;
private IReadOnlyList<IStorageItem> sharedStorageItems;
private string sharedCustomData;
private string sharedHtmlFormat;
private IReadOnlyDictionary<string, RandomAccessStreamReference> sharedResourceMap;
private IRandomAccessStreamReference sharedBitmapStreamRef;
private IRandomAccessStreamReference sharedThumbnailStreamRef;
private void ReportStarted()
{
this.shareOperation.ReportStarted();
}
private void ReportCompleted()
{
this.shareOperation.ReportCompleted();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
RegisterForShare();
try
{
this.shareOperation = (ShareOperation)e.Parameter;
await Task.Factory.StartNew(async () =>
{
ReportStarted();
// Retrieve data package properties.
this.sharedDataTitle = this.shareOperation.Data.Properties.Title;
this.sharedDataDescription = this.shareOperation.Data.Properties.Description;
this.shareQuickLinkId = this.shareOperation.QuickLinkId;
// Retrieve data package content.
if (this.shareOperation.Data.Contains(StandardDataFormats.Text))
{
try
{
this.sharedText = await this.shareOperation.Data.GetTextAsync();
}
catch (Exception exception)
{
// NotifyUser of error.
}
}
else if(this.shareOperation.Data.Contains(StandardDataFormats.Html))
{
try
{
this.sharedHtmlFormat = await this.shareOperation.Data.GetHtmlFormatAsync();
}
catch (Exception exception)
{
}
}
else if (this.shareOperation.Data.Contains(StandardDataFormats.Uri))
{
try
{
this.sharedUri = await this.shareOperation.Data.GetUriAsync();
}
catch (Exception exception)
{
}
}
// Get back to the UI thread.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (this.sharedText != null)
{
// Create a Note out of shared data.
CreateNote(this.sharedDataTitle, this.sharedText, null);
this.shareOperation.ReportDataRetrieved();
}
if (this.sharedUri != null)
{
CreateNote(this.sharedDataTitle, this.sharedUri.OriginalString, null);
this.shareOperation.ReportDataRetrieved();
}
if (this.sharedHtmlFormat != null)
{
CreateNote(this.sharedDataTitle, this.sharedHtmlFormat.ToString(), null);
this.shareOperation.ReportDataRetrieved();
}
});
});
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
}
if (e.NavigationMode == NavigationMode.Back)
{
navigatedBack = true;
}
base.OnNavigatedTo(e);
}
App.xaml.cs:
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
var rootFrame = new Frame();
rootFrame.Navigate(typeof(MainPage), args.ShareOperation);
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
Any help will be greatly appreciated.
In your package manifest, make sure you add the declaration for "share target"

Categories