Итак, у меня есть приложение А, которое является основным приложением. И затем у меня есть приложение B, в нем нет никаких действий, и оно используется приложением A в качестве службы для определения позиции пользователей. Чтобы обновить приложение B (с помощью APK, отправленного с нашего сервера), я использовал намерение с ACTION_VIEW
в качестве действия, запущенного из приложения A. Но так как оно устарело, это больше невозможно, поэтому я пытаюсь вместо этого используйте packageInstaller.
Я могу обновить приложение A с помощью packageInstaller, но когда я пытаюсь сделать то же самое с приложением B (обновить его из приложения A с помощью packageInstaller), я получил следующее сообщение:
I/ContentValues: 4, INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: Failed to parse /data/app/vmdl157182288.tmp/package: AndroidManifest.xml
, где 4
- это константа для PackageInstaller.STATUS_FAILURE_INVALID
.
. Вот как я устанавливаю обновление:
public static final String PACKAGE_INSTALLED_ACTION = "fr.whereIwork.SESSION_API_PACKAGE_INSTALLED";
PackageInstaller packageInstaller = this.owner.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL );
int sessionId;
try
{
sessionId = packageInstaller.createSession( params );
PackageInstaller.Session session = packageInstaller.openSession( sessionId );
Context context = this.owner.getApplicationContext();
try
{
OutputStream packageInSession = session.openWrite( "package", 0, -1 );
InputStream input;
Uri uri = Uri.parse( "file://" + this.appDirectory + this.apkFileName );
input = context.getContentResolver().openInputStream( uri );
if( input != null )
{
byte[] buffer = new byte[ 16384 ];
int n;
while ( ( n = input.read( buffer ) ) >= 0 )
{
packageInSession.write( buffer, 0, n );
}
}
else
{
throw new IOException ( "addApkToInstallSession" );
}
packageInSession.close(); // Need to close this stream.
input.close(); // Need to close this stream.
}
catch ( Exception exception )
{
exception.printStackTrace();
}
Intent intent = new Intent( context, this.owner.getClass() );
intent.setAction( PACKAGE_INSTALLED_ACTION );
intent.setFlags( Intent.FLAG_ACTIVITY_SINGLE_TOP );
PendingIntent pendingIntent = PendingIntent.getActivity( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT );
IntentSender statusReceiver = pendingIntent.getIntentSender();
session.commit( statusReceiver );
}
catch ( IOException e )
{
e.printStackTrace();
}
И вот что происходит, когда это делается:
public static final String PACKAGE_INSTALLED_ACTION = "fr.whereIwork.SESSION_API_PACKAGE_INSTALLED";
@Override
protected void onNewIntent( Intent intent )
{
Bundle extras = intent.getExtras();
if ( extras != null )
{
if ( PACKAGE_INSTALLED_ACTION.equals( intent.getAction() ) )
{
int status = extras.getInt( PackageInstaller.EXTRA_STATUS );
String message = extras.getString( PackageInstaller.EXTRA_STATUS_MESSAGE );
switch ( status )
{
case PackageInstaller.STATUS_PENDING_USER_ACTION :
Intent confirmIntent = ( Intent ) extras.get( Intent.EXTRA_INTENT );
startActivity( confirmIntent );
break;
case PackageInstaller.STATUS_SUCCESS :
Toast.makeText( this, "Install successfull !", Toast.LENGTH_SHORT ).show();
break;
case PackageInstaller.STATUS_FAILURE :
case PackageInstaller.STATUS_FAILURE_ABORTED :
case PackageInstaller.STATUS_FAILURE_BLOCKED :
case PackageInstaller.STATUS_FAILURE_CONFLICT :
case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE :
case PackageInstaller.STATUS_FAILURE_INVALID :
case PackageInstaller.STATUS_FAILURE_STORAGE :
Log.i( TAG, status + ", " + message ); // This is the log I talked about.
break;
default :
Toast.makeText( this, "Install failed ! " + status, Toast.LENGTH_SHORT ).show();
}
}
}
}
Теперь вот манифест из приложения A:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="fr.whereIwork.appA" >
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application
android:name=".NameOfOurApplicationA"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@drawable/ourLogo"
android:label="@string/application_name"
android:largeHeap="true"
android:theme="@style/ourAwesomeStyle"
android:vmSafeMode="true"
tools:ignore="GoogleAppIndexingWarning"
tools:replace="android:label" >
/*some crazy stuffs*/
<activity
android:name=".Login"
android:configChanges="keyboardHidden|orientation|screenSize"
android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
/*some more crazy stuffs for a whole lot of activities*/
</application>
</manifest>
И, наконец, манифест из приложения B:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="fr.whereIwork.appB">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:icon="@drawable/ourLogo"
android:label="@string/application_name"
android:name=".NameOfOurApplicationB">
/*some stuffs, but no activities*/
<service android:enabled="true" android:name="fr.whereIwork.appB.LocalisationService"
android:exported="true" android:process=":remote">
</service>
</application>
</manifest>
Есть еще несколько Манифест из библиотек, используемых обоими этими приложениями (и, по сути, еще двумя), но я не считаю, что они актуальны в этом случае (я могу ошибаться).
Я предполагаю, что Дело в том, что в приложении B нет активности, так или иначе, но я не могу найти работающего решение на net (похоже, это довольно частный случай). И он прекрасно работает при обновлении приложения А. Я в растерянности.
Любая помощь будет отличной, спасибо за чтение!