2017-11-04 1 views
0

Android O (api 26)에서 파일을 여는 중 일부 문제가 있습니다.Android에서 파일 열기 O가 작동하지 않지만 api에서 성공 25

성공적으로 다운로드 한 후 알림을 탭하면 아무 것도 나타나지 않습니다 (알림이 삭제됨). 그러나 api 25에서 동일한 작업을 수행하면 파일이 열리고 작동합니다.

디버깅 API에 대한 (26)

내가 뭔가를 바라나요 항상 방법 canOpenFile을 지적 false를 반환? 많은 도움을 주시면 감사하겠습니다.

알림 코드 : 의도 Openfile

public void finishedNotification(int id, String appName, String urlPath, boolean success) { 
     initSoundChannels(this); 
     NotificationCompat.Builder notification = new NotificationCompat.Builder(this, "default"); 

     notification.setContentTitle(appName) 
       .setContentText(success ? "Successfully downloaded" : "Download failed - file deleted") 
       .setSmallIcon(R.mipmap.ic_noti) 
       .setWhen(System.currentTimeMillis()) 
       .setColor(mApplication_.getInstance().getResources().getColor(R.color.apps_color)) 
       .setLargeIcon(BitmapFactory.decodeResource(mApplication_.getInstance().getResources(), R.mipmap.ic_launcher)) 
       .setOngoing(false) 
       .setPriority(Notification.PRIORITY_HIGH) 
       .setAutoCancel(true); 

     if (success) { 
      if (canOpenFile(urlPath)) { // ALWAYS false on API26?? 
       PendingIntent openFile = PendingIntent.getActivity(getApplicationContext(), 
         ACTION_OPEN_FILE.hashCode() + id, 
         openFile(urlPath), 
         PendingIntent.FLAG_CANCEL_CURRENT); 
       notification.setContentIntent(openFile); 
      } else { // being executed on api 26 
       PendingIntent openDownloads = PendingIntent.getBroadcast(getApplicationContext(), 
         ACTION_OPEN_DOWNLOADS.hashCode() + id, 
         new Intent(ACTION_OPEN_FILE), 
         PendingIntent.FLAG_CANCEL_CURRENT); 
       notification.setContentIntent(openDownloads); 
      } 
     } else { 
      Intent cancelIntent = new Intent(ACTION_FILE_CANCEL); 
      cancelIntent.putExtra("id", id); 
      PendingIntent cancel = PendingIntent.getBroadcast(mApplication_.getInstance(), 
        ACTION_FILE_CANCEL.hashCode() + id, 
        cancelIntent, 
        PendingIntent.FLAG_CANCEL_CURRENT); 
      notification.setContentIntent(cancel); 
     } 

     Notification builtNotification = notification.build(); 
     getNotificationManager().notify(id, builtNotification); 
    } 

:

private Intent openFile(String urlPath) { 
     File file = new File(urlPath); 

     Intent target = new Intent(Intent.ACTION_VIEW); 
     MimeTypeMap mime = MimeTypeMap.getSingleton(); 
     String ext = file.getName().substring(file.getName().lastIndexOf(".") + 1); 
     String type = mime.getMimeTypeFromExtension(ext); 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
      Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", file); 
      target.setDataAndType(uri, type); 
      target.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION); 
     } else { 
      Uri uri = Uri.fromFile(file); 
      target.setDataAndType(uri, type); 
      target.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     } 
     return target; 
    } 

CanOpenfile :

private boolean canOpenFile(String urlPath) { 
     PackageManager pm = getPackageManager(); 
     File file = new File(urlPath); 
     Intent intent = new Intent(Intent.ACTION_VIEW); 
     intent.setData(Uri.fromFile(file)); 
     ResolveInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 
     return info != null; 
    } 

답변

0

나는이 문제에 기여 할 수있는 두 가지 문제를 참조하십시오.

먼저, 사용자의 앱인 것처럼 보이는 암시 적 브로드 캐스트 (구성 요소 이름 대신 동작 문자열)를 사용하고 있습니다. 이는 보안 측면에서 볼 때 특히 좋은 아이디어는 아니며 Android 8.0 이상에서는 암시 적 브로드 캐스트가 일반적으로 금지됩니다. 따라서 new Intent(ACTION_OPEN_FILE)new Intent(this, WhateverTheReceiverClassIs.class).setAction(ACTION_OPEN_FILE)으로 바꾸십시오. 여기서 WhateverTheReceiverClassIsBroadcastReceiver 클래스가 무엇이든간에 그대로 사용하십시오.

두 번째로 canOpenFile()Uri.fromFile()을 사용하며 Urifile 체계를 제공합니다. file 스키마가 Android 7.0에서 일반적으로 금지되었으므로 Android 8.0 테스트 환경에서 <intent-filter>을 제공하는 앱이 전혀 없을 수도 있습니다. 또한 해당 코드는 openFile()과 일치하지 않습니다. Uri을 한 번 생성하고 두 시나리오 모두에 사용하십시오.

관련 문제