[android] 부여 된 INSTALL_PACKAGES 권한을 사용하여 자동으로 앱 설치
시스템에 apk를 자동으로 설치하려고합니다. 내 앱은 / system / app에 있으며 “android.permission.INSTALL_PACKAGES”권한이 성공적으로 부여되었습니다.
그러나이 권한을 사용하는 방법을 어디서도 찾을 수 없습니다. / data / app에 파일을 복사하려고했지만 성공하지 못했습니다. 또한이 코드를 사용해 보았습니다.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.parse("file:///sdcard/app.apk"),
"application/vnd.android.package-archive");
startActivity(intent);
그러나이 코드는 표준 설치 대화 상자를 엽니 다. 권한이 부여 된 루트없이 자동으로 앱을 설치하려면 어떻게해야 android.permission.INSTALL_PACKAGES
합니까?
추신 : 처음 시작할 때 폴더에서 시스템으로 많은 APK를 설치하는 앱을 작성 중입니다 (설치 마법사 교체). 펌웨어를 가볍게 만들기 위해 필요합니다.
내가 바이러스를 작성하고 있다고 생각하는 경우 : 모든 프로그램이 / data / app에 설치됩니다. 권한 Install_packages는 / system / app에 있거나 시스템 키로 서명 된 시스템 수준 프로그램에만 부여 할 수 있습니다. 그래서 바이러스는 거기에 도달 할 수 없습니다.
로 말했다 http://www.mail-archive.com/android-porting@googlegroups.com/msg06281.html 애플리케이션들이 install_packages 권한이있는 경우 설치 침묵 할 수 있습니다. 또한 패키지를 자동으로 설치하기 위해 Install_packages 권한이 필요하지 않습니다. 또한 http://www.androidzoom.com/android_applications/tools/silent-installer_wgqi.html
답변
첫 번째 방법은 Android의 기본 PackageInstaller 를 살펴 보는 것 입니다. 원하는 방식으로 해당 앱을 수정하거나 필요한 기능을 추출하는 것이 좋습니다.
특히 PackageInstallerActivity 와 그 방법 을 살펴보면 다음 과 onClickListener
같습니다.
public void onClick(View v) {
if(v == mOk) {
// Start subactivity to actually install the application
Intent newIntent = new Intent();
...
newIntent.setClass(this, InstallAppProgress.class);
...
startActivity(newIntent);
finish();
} else if(v == mCancel) {
// Cancel and finish
finish();
}
}
그러면 실제 설치 프로그램이 InstallAppProgress 클래스에 있음을 알 수 있습니다. 그 클래스를 살펴보면 이것이 initView
핵심 설치 프로그램 함수라는 것을 알 수 있으며 마지막으로하는 일은 PackageManager
의 installPackage
함수를 호출하는 것입니다.
public void initView() {
...
pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
}
다음 단계는 추상 클래스 인 PackageManager 를 검사 하는 것입니다. installPackage(...)
거기에서 기능을 찾을 수 있습니다. 나쁜 소식은 @hide로 표시되어 있다는 것입니다. 이것은 직접 사용할 수 없음을 의미합니다 (이 메서드를 호출하여 컴파일 할 수 없음).
/**
* @hide
* ....
*/
public abstract void installPackage(Uri packageURI,
IPackageInstallObserver observer,
int flags,String installerPackageName);
그러나 리플렉션을 통해이 메서드에 액세스 할 수 있습니다.
PackageManager
의 installPackage
기능이 어떻게 구현 되는지에 관심이 있다면 PackageManagerService를 살펴보십시오 .
요약
를 통해 패키지 관리자 개체를 Context
가져와야 getPackageManager()
합니다. 그런 다음 installPackage
리플렉션을 통해 함수를 호출 합니다.
답변
ADB가 앱을 설치하는 방법을 확인했습니다.
-APK
를 / data / local / tmp에 복사합니다
.- ‘shell : pm install /data/local/tmp/app.apk’를 실행합니다.
나는 다음을 수행 하여이 동작을 복제하려고 시도했습니다. (PC에서 USB 케이블 사용)
adb push app.apk /sdcard/app.apk
adb shell
$ pm install /sdcard/app.apk
이것은 작동합니다. 앱이 설치되었습니다.
다른 앱을 설치해야하는 애플리케이션 (AppInstall)을 만들었습니다.
(비 뿌리 장치, 일반적으로 설치)
이 수행합니다
Runtime.getRuntime().exec("pm install /sdcard/app.apk").waitFor();
그러나 이것은 오류가 있습니다 :
java.lang.SecurityException: Neither user 10019 nor current process has android.permission.INSTALL_PACKAGES.
오류가없는 AppInstall에 의해, 오후에 의해 발생되는 것 같다.
SecurityException은 AppInstall에 의해 포착되지 않고 앱이 충돌하지 않기 때문입니다.
루팅 된 기기 (동일한 앱과 AppInstall)에서 똑같은 작업을 시도했는데 매력처럼 작동했습니다.
(또한 일반적으로 / system 또는 다른 곳에 설치되지 않음)
AppInstall은 루트 권한을 요청하지 않았습니다.
그러나 셸은 항상 해당 장치 #
대신에 있기 때문 $
입니다.
Btw, / system에 앱을 설치하려면 루트가 필요합니다. 맞습니까?
나는 루팅되지 않은 장치에서 adb remount를 시도하고 얻었습니다.
remount failed: Operation not permitted.
그래서 루팅되지 않은 장치 에서 / system 일을 시도 할 수 없었습니다.
결론 : 루팅 된 기기를 사용해야합니다.
도움이되기를 바랍니다. 🙂
답변
최근 사용자 동의없이 설치를 구현하고 있습니다. API 레벨 21 이상을위한 키오스크 애플리케이션으로 환경을 완전히 제어 할 수있었습니다.
기본 요구 사항은 다음과 같습니다.
- API 레벨 21 이상
- 시스템 권한이있는 앱으로 업데이터를 설치하기위한 루트 액세스 .
다음 메소드는 InputStream에서 APK를 읽고 설치합니다.
public static boolean installPackage(Context context, InputStream in, String packageName)
throws IOException {
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(packageName);
// set params
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
OutputStream out = session.openWrite("COSU", 0, -1);
byte[] buffer = new byte[65536];
int c;
while ((c = in.read(buffer)) != -1) {
out.write(buffer, 0, c);
}
session.fsync(out);
in.close();
out.close();
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("info", "somedata"); // for extra data if needed..
Random generator = new Random();
PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(i.getIntentSender());
return true;
}
다음 코드는 설치를 호출합니다.
try {
InputStream is = getResources().openRawResource(R.raw.someapk_source);
installPackage(MainActivity.this, is, "com.example.apk");
} catch (IOException e) {
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
모든 것이 작동하려면 INSTALL_PACKAGES
권한 이 절실히 필요합니다 . 그렇지 않으면 위 코드가 조용히 실패합니다.
<uses-permission
android:name="android.permission.INSTALL_PACKAGES" />
이 권한을 얻으려면 루트가 필요한 시스템 애플리케이션으로 APK를 설치해야합니다 (업데이터 애플리케이션을 설치 한 후에는 루트없이 작동하는 것 같습니다).
시스템 애플리케이션으로 설치하기 위해 서명 된 APK를 생성하고
adb push updater.apk /sdcard/updater.apk
다음으로 이동 system/priv-app
-FS를 다시 마운트해야 함 (이것이 루트가 필요한 이유입니다)
adb shell
su
mount -o rw,remount /system
mv /sdcard/updater.apk /system/priv-app
chmod 644 /system/priv-app/updater.apk
어떤 이유로 간단한 디버그 버전에서는 작동하지 않았지만 어떤 이유로 애플리케이션 이 선택되지 않으면 logcat 에 유용한 정보가 표시됩니다 priv-app
.
답변
정의해야합니다
<uses-permission
android:name="android.permission.INSTALL_PACKAGES" />
매니페스트에서 시스템 파티션 (/ system / app)에 있거나 제조업체에서 서명 한 애플리케이션이 있는지 여부에 관계없이 INSTALL_PACKAGES 권한을 갖게됩니다.
내 제안은 리플렉션을 통해 installPackages를 호출하고 패키지를 설치하고 실제 메서드를 호출하는 방법으로 jar를 내보내는 데 사용되는 1.5 호환성 수준의 작은 Android 프로젝트를 만드는 것입니다. 그런 다음 프로젝트에서 jar를 가져 오면 패키지를 설치할 준비가 된 것입니다.
답변
나는 루팅 된 Android 4.2.2에서 시도 했으며이 방법은 나를 위해 작동합니다.
private void installApk(String filename) {
File file = new File(filename);
if(file.exists()){
try {
final String command = "pm install -r " + file.getAbsolutePath();
Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
proc.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
답변
그 시간에 아무도 대답하지 않았기 때문에 어떻게해야할지 몰랐고이 허가에 대한 문서를 찾지 못했습니다. 그래서 나만의 해결책을 찾았습니다. 당신의 것보다 더 나쁘지만 어쨌든 이것은 해결책입니다.
/ data / app에 777 권한을 설정 한 busybox를 설치했습니다 (보안에 대해서는 신경 쓰지 않습니다). 그런 다음 앱에서 “busybox 설치”를 실행했습니다. 이것은 작동하지만 큰 보안 누출이 있습니다. 권한 777을 설정하면 루트가 필요하지 않습니다.
답변
android.content.pm.IPackageInstallObserver
리플렉션으로 숨겨진 API 를 사용할 수 있습니다 .
public class PackageManagement {
public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
public static final int INSTALL_SUCCEEDED = 1;
private static Method installPackageMethod;
private static Method deletePackageMethod;
static {
try {
installPackageMethod = PackageManager.class.getMethod("installPackage", Uri.class, IPackageInstallObserver.class, Integer.TYPE, String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static void installPackage(PackageManager pm, Uri mPackageUri, IPackageInstallObserver observer, int installFlags, String installerPackageName) {
try {
installPackageMethod.invoke(pm, mPackageUri, observer, installFlags, installerPackageName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
android.content.pm.IPackageInstallObserver
프로젝트로 가져 옵니다. 앱은 시스템이어야합니다. android.permission.INSTALL_PACKAGES
매니페스트 파일에서 권한 을 활성화해야 합니다.