Domanda Controllare versione, scaricare, installare e rimuovere

Stato
Discussione chiusa ad ulteriori risposte.

hacksoldier98

Utente Silver
7 Gennaio 2016
261
11
7
71
Salve io ho cercato tanto su internet ma non sono riuscito a trovare niente tranne questo

Java:
MainActivity
@Override
public void onCreate(Bundle savedInstanceState) {
//omissis
if (isOnline()) { //Se il telefono è connesso, controlla gli aggiornamenti
checkForUpdates();
}
}



//Controllo se è disponibile la connessione ad internet
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo().isConnectedOrConnecting( );
}

public void checkForUpdates() {
String url = "http://www.server.com/yourapp.apk"; //L'indirizzo dove è hostato l'apk
String PATH = Environment.getExternalStorageDirectory() + "/download/"; //Il percorso in cui verrà scaricato
File file = new File(PATH); //Crea un nuovo file nel percorso specificato
file.mkdirs(); //Se necessario, crea le sottocartelle mancanti
File outputFile = new File(file, "yourapp.apk"); //Scrive il file
UpdateWithoutPlayStore.downloadFile(url, outputFile);
UpdateWithoutPlayStore.installApp(context);     <- ERRORE 
UpdateWithoutPlayStore.deleteApk("yourapp.apk");
}

UpdateWithoutPlayStore class

//Tutti gli import del caso
public class UpdateWithoutPlayStore {

public static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url); //Prende l'url del sito
URLConnection conn = u.openConnection(); //Si collega al sito
int contentLength = conn.getContentLength(); //Restituisce la lunghezza in byte del file da scaricare

DataInputStream stream = new DataInputStream(u.openStream()); //Crea un oggetto della classe DataInputStream - dovrebbe servire per il download vero e proprio

byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();

DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile)); //Crea un oggetto della classe DataOuyputStream
fos.write(buffer); //Scrive il file
fos.flush(); //Svuota il buffer dell'oggetto fos (potrei aver detto una fesseria)
fos.close(); //Chiude fos
} catch (FileNotFoundException e) { //Se il file non è stato trovato, riporta questo errore
Log.e("FileNotFoundException", e + "");
} catch (IOException e) { //Se ci sono stati problemi di I/O riporta questo altro errore
Log.e("IOException", e + "");
}
}


public static void installApp(Context mycontext) {
Intent installer = new Intent(); //Crea un nuovo intent
installer.setAction(android.content.Intent.ACTION_ VIEW);
String PATH = "file://" + Environment.getExternalStorageDirectory() + "/download/yourapp.apk"; //Specifica il perccorso dove è stato salvvvato il file
installer.setDataAndType(Uri.parse(PATH), "application/vnd.android.package-archive");
mycontext.startActivity(installer); //Lo installa
}

public static void deleteApk(String fileName) {
String fullPath = Environment.getExternalStorageDirectory() + "/download/";
try {
File file = new File(fullPath, fileName);
if (file.exists()) {
file.delete();
Log.e("FileStatus","deleted");
}
} catch (Exception e){
Log.e("Exception",e.getMessage());
}
}
}

l'errore sta sul installare l'apk poiché sinceramente non saprei come inizializzarlo.

l'altro problema era se per caso esistesse un modo dove la mia app possa anche controllare la versione aggiornata su quel sito.. è possibile?
 
ok non l'ho vista però non capisco costa sta a significare questo rigo
URL url = new URL(sUrl[0]);

perché sUrl ha tra parentesi quadre lo 0?

anzi ora mi da errore sempre nel context di questa riga
this.context.startActivity(i);
 
io il codice l'ho messo nel mainActivity dentro al tasto dove dice aggiorna app.. l'errore del context è il seguente: Cannot resolve symbol 'context'
 
Incompatible types:
Requiered : android.content.Context
Found: android.view.ViewOnclickListener

questo perché il codice di installazione l'ho messo nel OnClickListener del bottone... secondo me dovrei metterlo in una classe
 
allora , prima di tutto , questo codice non ci va proprio nel tasto , tu hai detto che appena l'utente va online , esegui questi controlli , dev'essere una cosa fatta in automatico , quindi non devi metterlo in un tasto , ma in un servizio , che si attiva quando l'utente va online , e dopo esegue tutto il resto , quindi hai già sbagliato a posizionare il codice
 
public void installApk (String path) {
Intent i = new Intent();
Context context = this;
i.setAction(Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive" );
this.context.startActivity(i);
}
sempre context nell'ultima riga da sempre errore: Cannot resolve symbol 'context'

ho letto meglio il sito... io però devo farlo installare solo quando schiaccia il bottone e controllerebbe se la versione fosse aggiornata
 
Il context ti permette di passare i dati dell'applicazione , cosi dopo riesci ad accedere alle tue risorse e tutto il resto , se te lo chiede, ci sono vari metodi per passarlo , uno di questi è il getapplication context , a sto punto visto che (this = context) non va , prova ad utilizzare questa funzione
Codice:
i = new Intent(getApplicationContext(),Nomeclasse.class);
e poi fai cominciare l'activity , però stai attento , ci sono vari tipi , alcuni per esempio non ti tornano niente , altri ti ritornano dei risultati ,
usa quella che serve a te .
Codice:
startActivity(i);
prova e fammi sapere.
 
per nome classe cosa ci metto?

anzi ho fatto in questo modo

Java:
    private long DownloadApk (Uri apkuri) {

        long downloadReference;

        DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        DownloadManager.Request request = new DownloadManager.Request(apkuri);

        request.setTitle("FIle apk Download");
        request.setDescription("File apk aggiornata");
        request.setDestinationInExternalFilesDir(MainActivity.this, Environment.DIRECTORY_DOWNLOADS, "4Serale.apk");
        downloadReference = downloadManager.enqueue(request);
        return downloadReference;
    }

    public void installApp() {
        Intent installer = new Intent();
        installer.setAction(android.content.Intent.ACTION_VIEW);
        String PATH = "file://" + Environment.getExternalStorageDirectory() + "/Download/myapp.apk"; 
        installer.setDataAndType(Uri.parse(PATH), "application/vnd.android.package-archive");
        startActivity(installer);
    }

solo che l'app non gli lascia il tempo di scaricare l'app.. come faccio gli do il comando tipo sleep per un tot di tempo? pero non avrebbe senso anche perché comunque ognuno ha la sua velocità di download.. come posso fare?
 
Ultima modifica:
non ci metti nessuna classe l'intent prende due valori il primo sono i dati , il secondo l'azione , nel tuo caso dovrai eseguire un'azione non una classe .

Ho controllato ancora e ho trovato una soluzione ancora più performante , prova questa

Codice:
//Trova la directory dove scaricherai il file
   String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
   String fileName = "AppName.apk";
   destination += FileName; //nome app
   final Uri uri = Uri.parse("file://" + destination);

   //Elimini se il file di aggiornamento esiste già
   File file = new File(destination);
   if (file.exists())
       file.delete();

   //Predni l'url dell'apk sul server
   String url = Main.this.getString(R.string.update_app_url);

   //imposta il downloadmanager
   DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
   request.setDescription(Main.this.getString(R.string.notification_description));
   request.setTitle(Main.this.getString(R.string.app_name));

   //imposta la destinazione
   request.setDestinationUri(uri);

   //aggiungi il file al download manager
   final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
   final long downloadId = manager.enqueue(request);

   //imposta il BroadcastReceiver per installare l'app quando l'apk è scaricato
   BroadcastReceiver onComplete = new BroadcastReceiver() {
       public void onReceive(Context ctxt, Intent intent) {
           Intent install = new Intent(Intent.ACTION_VIEW);
           install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
           install.setDataAndType(uri,
                   manager.getMimeTypeForDownloadedFile(downloadId));
           startActivity(install);

           unregisterReceiver(this);
           finish();
       }
   };
   //avvisa che l'apk è stata scaricata
   registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));


Edit : scusami , oltre all'azione , puoi anche mettere la classe che verrà eseguita
 
c'è con un telefono normale alla versione 4.4.2 collegandolo in adb e tutto il resto funziona poi se creo l'app e lo metto dentro a un altro telefono con root, custom rom 6.0.1 non va..
 
Se sul telefono non va , può darsi che siano i permessi , perchè android 6 è diverso dai precedenti , dalla 5 in giù , bastava mettere i permessi che ti servivano nel manifest dell'app , invece con android 6 in poi, per ogni permesso che ti serve (per esempio accedere allo storage o altro) devi mostrare una finestra pop-up e chiedere il permesso all'utente , quindi devi gestire questa cosa , se non hai tempo , installa l'app , vai nelle impostazioni del cel , dove ci sono tutte le app , trova la tua , e troverai una sezione apposta per i permessi , attivali tutti , e prova a far ripartire l'app.
 
no anzi ho tempo per farlo se per te non è un problema se riesci a spiegarmelo come fare.. solo che pensavo.. ma se l'app la installo io che ho la 6 mi da questo errore allora io risolvo facendo come hai detto tu... pero se poi lo installa uno che ha 5 o inferiore può essere che l'app possa chiedere anche a quel utente questo permesso pop up?
 
No , perchè tu prima di chiedere i permessi controlli la versione di Android che ha l'utente , quindi se è inferiore al 6 non mostro nemmeno quelle finestre
 
Perfetto , allora , io questa cosa non l'avevo mai fatta , ho sempre dato i permessi tramite impostazioni perchè quando era appena uscito il 6 era un casino , ma a quanto pare hanno semplificato le cose , esistono adesso delle funzioni apposta , prova a dare un'occhiata qua , sono molto semplici , ricordati , questa parte di codice andrà scritta prima di eseguire i download o qualsiasi cosa richieda i permessi , o potresti mostrarli subito appena apri l'app , decidi tu dove metterli
 
no scusami non capisco molto.. quale codice devo prendere questo?
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);

no scusami ho fatto grazie sei stato davvero gentilissimo :D

ah pero come faccio il controllo della versione dell'app?
 
Stato
Discussione chiusa ad ulteriori risposte.