안 드 로 이 드 통화 자동 녹음 서비스 실현

21932 단어 android녹음 하 다.
본 논문 의 사례 는 안 드 로 이 드 가 통화 자동 녹음 서 비 스 를 실현 하 는 구체 적 인 코드 를 공유 하여 여러분 께 참고 하 시기 바 랍 니 다.구체 적 인 내용 은 다음 과 같 습 니 다.
필요:
①:통화 자동 녹음;
②:인터페이스 가 없 으 면 하나의 service 일 뿐 입 니 다.
③:녹음 자동 압축 업로드;
④:사용자 가 백 엔 드 를 청소 할 때 service 가 죽 으 면 안 된다 고 요구 합 니 다.
⑤:안정성:1.네트워크 가 없 는 경우.2.업로드 실패;3.서비스 오류.
해결 방안:
①:통화 자동 녹음
서 비 스 를 시작 하여 사용자 의 휴대 전화 통화 상 태 를 감청 하고 사용자 가 통화 상태 에 있 는 것 을 감지 하면 즉시 녹음 을 시작 하고 통화 가 끝 난 후에 녹음 을 중단 하고 파일 을 저장 합 니 다.
이 기능 의 전제 조건:
1.녹음 권한,읽 기와 쓰기 저장 공간의 권한,통화 상 태 를 읽 을 수 있 는 권한;
2.서 비 스 는 정지 되 어 서 는 안 됩 니 다.그렇지 않 으 면 녹음 할 수 없습니다.
3.시동 걸 기(사용자 가 매번 시동 을 걸 때마다 자발적으로 서 비 스 를 켜 게 해 서 는 안 된다)
②:인터페이스 없 이 하나의 service
방안 ①
일반적인 서 비 스 는 켜 진 방송 을 감청 하고 사용자 가 켜 졌 을 때 서 비 스 를 시작 합 니 다.하지만 서 비 스 는 시작 되 지 않 았 다.service 를 시작 하려 면 activity 가 있어 야 합 니 다.이 activity 를 열지 않 더 라 도.
진정 으로 프로젝트 를 할 때 PM 은 이해 할 수 없 는 여러 가지 수 요 를 제기 할 것 이다.예 를 들 어 본 시스템,PM 은 본 응용 은 녹음 서비스 일 뿐 어떠한 인터페이스 도 있어 서 는 안 되 고 핸드폰 데스크 톱 에 응용 아이콘 이 나타 나 서 는 안 된다 고 요구한다.따라서 방안 ① 은 불가능 하 다.
방안 ②
Android 핸드폰 은 설정 에서 모두 보조 기능(개별 핸드폰 은 무장 애 라 고도 함)을 가진다.이 를 이용 하면 우 리 는 강력 한 기능 을 실현 할 수 있다.전 제 는 사용자 가 우리 의 보조 기능 을 켜 는 것 이다.보너스 소프트웨어 를 빼 앗 는 것 은 보조 기능 을 이용 하여 이 루어 진 것 이다.

③:녹음 자동 압축 업로드
우 리 는 업로드 하기 전에 파일 을 압축 처리 한 후에 업로드 하면 된다.
④:사용자 가 백 엔 드 를 정리 할 때 service 가 죽 으 면 안 된다 고 요구 합 니 다.
죽 임 을 당 하지 않 는 서 비 스 는 시스템 서비스 만 있 을 지도 모른다.물론 QQ,위 챗 같은 가족 통 도 할 수 있다.큰 회 사 는 제조 업 체 와 합작 할 수 있 으 며,그들의 응용 은 쉽게 죽 이지 않 을 수 있다.물론 이렇게 하 는 것 을 제창 하지 않 는 다.이것 이 바로 스 팸 소프트웨어 로 안 드 로 이 드 개발 의 아름 다운 환경 을 파괴 했다.
사실 서 비 스 를 시스템 서비스 로 설정 할 수 있다 면 사용자 가 자발적으로 보조 기능 페이지 에서 서 비 스 를 끄 지 않 으 면 백 엔 드 는 서 비 스 를 고 칠 수 없다.본인 은 샤 오미 휴대 전화 에서 테스트 해 시스템 급 서비스 로 설정 한 뒤 백 스테이지 청소 시 서비스 가 죽 더 라 도 빠르게 재가 동 된다.(관심 있 는 학생 은 한번 해 보 세 요)
⑤:안정성:1.네트워크 가 없 는 경우.2.업로드 실패;3.서비스 오류
생각:
네트워크 가 없 는 경우 녹음 파일 의 주 소 를 저장 합 니 다.(저장 방식 은 Sqlite,Shared preferences 등 이 많 습 니 다.)업로드 에 실패 한 것 도 마찬가지 입 니 다.실패 한 원인 은 여러 가지 가 있 을 수 있 습 니 다.네트워크 가 끊 기 고 인터페이스 가 잘못 되 었 을 때 다시 업로드 할 수 있 습 니 다.그러면 녹음 파일 을 잃 어 버 리 지 않 습 니 다.
코드 가 간단 하고 주석 이 상세 합 니 다.
프로젝트 구성:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--                         -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<!--        -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--    wifi    -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

<service
 android:name=".service.RecorderService"
 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
 <intent-filter>
  <action android:name="android.accessibilityservice.AccessibilityService" />
 </intent-filter>
 <meta-data
  android:name="android.accessibilityservice"
  android:resource="@xml/accessible_service_config" />
</service>

/**
 *           (  、         )。
 * Created by wang.ao in 2017/2/24.
 */

public class RecorderService extends AccessibilityService {
 private static final String TAG = "RecorderService";
 private static final String TAG1 = "      ";
 /**
  *     
  */
 private MediaRecorder recorder;
 private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 /**
  *       ,             
  */
 private OutCallReceiver outCallReceiver;
 private IntentFilter intentFilter;
 /**
  *         ,         ,               
  */
 private NetworkConnectChangedReceiver networkConnectChangedReceiver;
 private IntentFilter intentFilter2;
 /**
  *            
  */
 private String currentCallNum = "";
 /**
  *        
  */
 private int previousStats = 0;
 /**
  *          
  */
 private String currentFile = "";
 /**
  *           
  */
 private SharedPreferences unUploadFile;
 private String dirPath = "";
 private boolean isRecording = false;

 @Override
 protected void onServiceConnected() {
  Log.i(TAG, "onServiceConnected");
  Toast.makeText(getApplicationContext(), "         ", Toast.LENGTH_LONG).show();
 }

 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
  // TODO Auto-generated method stub
  Log.i(TAG, "eventType " + event.getEventType());
 }

 @Override
 public void onInterrupt() {
  // TODO Auto-generated method stub
  Log.i(TAG, "onServiceConnected");
 }

 @Override
 public boolean onUnbind(Intent intent) {
  return super.onUnbind(intent);
 }

 @Override
 public void onCreate() {
  super.onCreate();
  TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
  //       
  tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
  outCallReceiver = new OutCallReceiver();
  intentFilter = new IntentFilter();
  //        
  intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
  registerReceiver(outCallReceiver, intentFilter);
  //         
  networkConnectChangedReceiver = new NetworkConnectChangedReceiver();
  intentFilter2 = new IntentFilter();
  //            
  intentFilter2.addAction("android.net.conn.CONNECTIVITY_CHANGE");
  intentFilter2.addAction("android.net.wifi.WIFI_STATE_CHANGED");
  intentFilter2.addAction("android.net.wifi.STATE_CHANGE");
  //             
  registerReceiver(networkConnectChangedReceiver, intentFilter2);
  unUploadFile = getSharedPreferences("un_upload_file", 0);
  unUploadFile.edit().putString("description", "            ").commit();
  dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/com.ct.phonerecorder/";
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  Toast.makeText(getApplicationContext(), "     ,      ,       ", Toast.LENGTH_LONG).show();
  if (outCallReceiver != null) {
   unregisterReceiver(outCallReceiver);
  }
  if (networkConnectChangedReceiver != null) {
   unregisterReceiver(networkConnectChangedReceiver);
  }
 }

 class MyListener extends PhoneStateListener {
  @Override
  public void onCallStateChanged(int state, String incomingNumber) {
   // TODO Auto-generated method stub
   Log.d(TAG1, "    " + incomingNumber);
   switch (state) {
    case TelephonyManager.CALL_STATE_IDLE:
     Log.d(TAG1, "  ");
     if (recorder != null && isRecording) {
      recorder.stop();//     
      recorder.release();
      recorder = null;
      Log.d("  ", "    ,    ");
      uploadFile(currentFile);
     }
     isRecording = false;
     break;
    case TelephonyManager.CALL_STATE_RINGING:
     Log.d(TAG1, "    " + incomingNumber);
     //      

     break;
    case TelephonyManager.CALL_STATE_OFFHOOK:
     Log.d(TAG1, "  " + (!incomingNumber.equals("") ? incomingNumber : currentCallNum));
     initRecord(!incomingNumber.equals("") ? incomingNumber : currentCallNum);
     //     
     if (recorder != null) {
      recorder.start();
      isRecording = true;
     }
    default:
     break;
   }
   super.onCallStateChanged(state, incomingNumber);
  }

 }

 /**
  *       ,        。
  * ①    :    ;
  * ②     :      ,             ;
  * ③       ,       ,      。
  */
 public void uploadFile(String file) {
  ZipUtils.zipFile(dirPath + file, dirPath + file + ".zip");
  if (NetWorkUtils.isNetworkConnected(getApplicationContext())) {
   //    
//   OkHttpUtils.postFile()
  } else {
   saveUnUploadFIles(dirPath + file + ".zip");
  }
 }

 /**
  *           
  *
  * @param file           
  */
 private void saveUnUploadFIles(String file) {
  String files = unUploadFile.getString("unUploadFile", "");
  if (files.equals("")) {
   files = file;
  } else {
   StringBuilder sb = new StringBuilder(files);
   files = sb.append(";").append(file).toString();
  }
  unUploadFile.edit().putString("unUploadFile", files).commit();
 }

 /**
  *             ,             ,    
  */
 public void uploadUnUploadedFiles() {
  //           ,        
  String files = unUploadFile.getString("unUploadFile", "");
  unUploadFile.edit().putString("unUploadFile", "").commit();
  if (files.equals("")) {
   return;
  }
  String[] fileArry = files.split(";");
  int len = fileArry.length;
  for (String file : fileArry) {
   upload(file);
  }
 }

 /**
  *     
  *
  * @param file       
  */
 public void upload(final String file) {
  File file1 = new File(file);
  if (file1 == null || !file1.exists()) {
   //     
   return;
  }
  if (!NetWorkUtils.isNetworkConnected(getApplicationContext())) {
   saveUnUploadFIles(file);
   return;
  }
  Map<String, String> map = new HashMap<String, String>();
  map.put("type", "1");
  final String url = "http://192.168.1.158:8082/uploader";
  OkHttpUtils.post()//
    .addFile("mFile", file1.getName(), file1)//
    .url(url)//
    .params(map).build()//
    .execute(new StringCallback() {

     @Override
     public void onResponse(String response, int id) {
      Log.e(TAG, "   response=" + response);
     }

     @Override
     public void onError(Call call, Exception e, int id) {
      Log.e(TAG, "   response=" + e.toString());
      saveUnUploadFIles(file);
     }
    });
 }

 /**
  *       ,         
  *
  * @param incomingNumber     
  */
 private void initRecord(String incomingNumber) {
  previousStats = TelephonyManager.CALL_STATE_RINGING;
  recorder = new MediaRecorder();
  recorder.setAudioSource(MediaRecorder.AudioSource.MIC);// Microphone
  recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);//     3gp  
  File out = new File(dirPath);
  if (!out.exists()) {
   out.mkdirs();
  }
  recorder.setOutputFile(dirPath
    + getFileName((previousStats == TelephonyManager.CALL_STATE_RINGING ? incomingNumber : currentCallNum))
  );
  recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//         
  try {
   recorder.prepare();//     
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  *          
  *
  * @param incomingNumber     
  * @return          
  */
 private String getFileName(String incomingNumber) {
  Date date = new Date(System.currentTimeMillis());
  currentFile = incomingNumber + " " + dateFormat.format(date) + ".mp3";
  return currentFile;
 }

 /**
  *        ,       
  */
 public class OutCallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
   Log.d(TAG1, "         :" + currentCallNum);
   if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
    currentCallNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    Log.d(TAG1, "         :" + currentCallNum);
   } else {
    Log.d(TAG1, "   ,     ");
   }
  }
 }

 /**
  *     change     
  */
 public class NetworkConnectChangedReceiver extends BroadcastReceiver {
  private static final String TAG = "network status";

  @Override
  public void onReceive(Context context, Intent intent) {
   /**
    *            ,  wifi           。.
    *           。wifi    ,  ,                。 log
    *                       ,       wifi,                
    */
   if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
    ConnectivityManager manager = (ConnectivityManager) context
      .getSystemService(Context.CONNECTIVITY_SERVICE);
    Log.i(TAG, "CONNECTIVITY_ACTION");

    NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
    if (activeNetwork != null) { // connected to the internet
     if (activeNetwork.isConnected()) {
      //      
      if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
       // connected to wifi
       Log.e(TAG, "  WiFi     ");
      } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
       // connected to the mobile provider's data plan
       Log.e(TAG, "           ");
      }
      uploadUnUploadedFiles();
     } else {
      Log.e(TAG, "        ,           ");
     }

    } else { // not connected to the internet
     Log.e(TAG, "        ,           ");
    }


   }
  }
 }

}

/**
 *            
 * Created by wang.ao in 2017/2/24.
 */

public class NetWorkUtils {
 /**
  *          
  * @param context
  * @return
  */
 public static boolean isNetworkConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
   if (mNetworkInfo != null) {
    return mNetworkInfo.isAvailable();
   }
  }
  return false;
 }


 /**
  *   WIFI      
  * @param context
  * @return
  */
 public static boolean isWifiConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mWiFiNetworkInfo = mConnectivityManager
     .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
   if (mWiFiNetworkInfo != null) {
    return mWiFiNetworkInfo.isAvailable();
   }
  }
  return false;
 }


 /**
  *   MOBILE      
  * @param context
  * @return
  */
 public static boolean isMobileConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mMobileNetworkInfo = mConnectivityManager
     .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
   if (mMobileNetworkInfo != null) {
    return mMobileNetworkInfo.isAvailable();
   }
  }
  return false;
 }


 /**
  *              
  * @param context
  * @return
  */
 public static int getConnectedType(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
   if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
    return mNetworkInfo.getType();
   }
  }
  return -1;
 }


 /**
  *           :    0:WIFI  1:3G  2:2G  3
  *
  * @param context
  * @return
  */
 public static int getAPNType(Context context) {
  int netType = 0;
  ConnectivityManager connMgr = (ConnectivityManager) context
    .getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
  if (networkInfo == null) {
   return netType;
  }
  int nType = networkInfo.getType();
  if (nType == ConnectivityManager.TYPE_WIFI) {
   netType = 1;// wifi
  } else if (nType == ConnectivityManager.TYPE_MOBILE) {
   int nSubType = networkInfo.getSubtype();
   TelephonyManager mTelephony = (TelephonyManager) context
     .getSystemService(Context.TELEPHONY_SERVICE);
   if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
     && !mTelephony.isNetworkRoaming()) {
    netType = 2;// 3G
   } else {
    netType = 3;// 2G
   }
  }
  return netType;
 }
}

public class ZipUtils {
 private static final int BUFF_SIZE = 1024;

 /**
  * @param zos      
  * @param parentDirName    
  * @param file        
  * @param buffer     
  *    
  * @return               ,      
  */
 private static boolean zipFile(ZipOutputStream zos, String parentDirName, File file, byte[] buffer) {
  String zipFilePath = parentDirName + file.getName();
  if (file.isDirectory()) {
   zipFilePath += File.separator;
   for (File f : file.listFiles()) {
    if (!zipFile(zos, zipFilePath, f, buffer)) {
     return false;
    }
   }
   return true;
  } else {
   try {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    ZipEntry zipEntry = new ZipEntry(zipFilePath);
    zipEntry.setSize(file.length());
    zos.putNextEntry(zipEntry);
    while (bis.read(buffer) != -1) {
     zos.write(buffer);
    }
    bis.close();
    return true;
   } catch (FileNotFoundException ex) {
    ex.printStackTrace();
   } catch (IOException ex) {
    ex.printStackTrace();
   }
   return false;
  }
 }

 /**
  * @param srcPath          
  * @param dstPath     zip  
  * @return                        (   windows       )
  */
 public static boolean zipFile(String srcPath, String dstPath) {
  File srcFile = new File(srcPath);
  if (!srcFile.exists()) {
   return false;
  }
  byte[] buffer = new byte[BUFF_SIZE];
  try {
   ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dstPath));
   boolean result = zipFile(zos, "", srcFile, buffer);
   zos.close();
   return result;
  } catch (FileNotFoundException ex) {
   ex.printStackTrace();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
  return false;
 }

 /**
  * @param srcPath     zip  
  * @param dstPath zip         
  * @return            ,        (   windows       )
  */
 public static boolean unzipFile(String srcPath, String dstPath) {
  if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(dstPath)) {
   return false;
  }
  File srcFile = new File(srcPath);
  if (!srcFile.exists() || !srcFile.getName().toLowerCase(Locale.getDefault()).endsWith("zip")) {
   return false;
  }
  File dstFile = new File(dstPath);
  if (!dstFile.exists() || !dstFile.isDirectory()) {
   dstFile.mkdirs();
  }
  try {
   ZipInputStream zis = new ZipInputStream(new FileInputStream(srcFile));
   BufferedInputStream bis = new BufferedInputStream(zis);
   ZipEntry zipEntry = null;
   byte[] buffer = new byte[BUFF_SIZE];
   if (!dstPath.endsWith(File.separator)) {
    dstPath += File.separator;
   }
   while ((zipEntry = zis.getNextEntry()) != null) {
    String fileName = dstPath + zipEntry.getName();
    File file = new File(fileName);
    File parentDir = file.getParentFile();
    if (!parentDir.exists()) {
     parentDir.mkdirs();
    }
    FileOutputStream fos = new FileOutputStream(file);
    while (bis.read(buffer) != -1) {
     fos.write(buffer);
    }
    fos.close();
   }
   bis.close();
   zis.close();
   return true;
  } catch (FileNotFoundException ex) {
   ex.printStackTrace();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
  return false;
 }
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기